import { Injectable } from "@nestjs/common";
import { PrismaService } from "../../prisma/prisma.service";
import Expo from "expo-server-sdk";

@Injectable()
export class PushService {
  private expo = new Expo();

  constructor(private prisma: PrismaService) {}

  async registerDevice(userId: string, dto: { token: string; platform: "ios"|"android"|"web"; deviceId?: string }) {
    const device = await this.prisma.pushDevice.upsert({
      where: { token: dto.token },
      update: { userId, platform: dto.platform, deviceId: dto.deviceId ?? null, enabled: true, updatedAt: new Date() },
      create: { userId, platform: dto.platform, token: dto.token, deviceId: dto.deviceId ?? null, enabled: true },
    });
    return { ok: true, deviceId: device.id };
  }

  async disableDevice(userId: string, token: string) {
    const existing = await this.prisma.pushDevice.findUnique({ where: { token } });
    if (!existing || existing.userId !== userId) return { ok: true };
    await this.prisma.pushDevice.update({ where: { token }, data: { enabled: false, updatedAt: new Date() } });
    return { ok: true };
  }

  async sendToUser(userId: string, payload: { title: string; body: string; data?: any }) {
    const devices = await this.prisma.pushDevice.findMany({
      where: { userId, enabled: true },
      select: { token: true },
    });

    const tokens = devices.map(d => d.token).filter(t => Expo.isExpoPushToken(t));
    if (!tokens.length) return { ok: true, sent: 0 };

    const messages: Expo.ExpoPushMessage[] = tokens.map(token => ({
      to: token,
      sound: "default",
      title: payload.title,
      body: payload.body,
      data: payload.data ?? {},
      priority: "high",
    }));

    const chunks = this.expo.chunkPushNotifications(messages);
    let tickets: Expo.ExpoPushTicket[] = [];

    for (const chunk of chunks) {
      const t = await this.expo.sendPushNotificationsAsync(chunk);
      tickets = tickets.concat(t);
    }

    // Basic disable on error (better with receipts later)
    for (let i = 0; i < tickets.length; i++) {
      const ticket = tickets[i];
      if (ticket.status === "error") {
        const token = messages[i]?.to as string;
        if (token) {
          await this.prisma.pushDevice.updateMany({
            where: { token },
            data: { enabled: false, updatedAt: new Date() },
          });
        }
      }
    }

    return { ok: true, sent: tokens.length };
  }
}
