import { Injectable } from '@nestjs/common';
import { ClsService } from 'nestjs-cls';
import type { SubscribePayload, PendingCountResponse } from '@sar/api-interface';
import type { WorkspaceClsStore } from '../workspace/workspace.types';
import { PushService, type PushPayload } from './push.service';

// Situa: 1=Pendente Aprovação
const SITUA_PENDENTE = 1;

@Injectable()
export class NotificationsService {
  constructor(
    private readonly cls: ClsService<WorkspaceClsStore>,
    private readonly push: PushService,
  ) {}

  async subscribe(userId: string, role: string, dto: SubscribePayload): Promise<void> {
    const prisma = this.cls.get('prisma');
    if (!prisma) throw new Error('prisma não disponível no CLS');
    const idEmpresa = this.cls.get('idEmpresa');
    const codVendedor = userId ? parseInt(userId, 10) : null;

    await prisma.pushSubscription.upsert({
      where: { endpoint: dto.endpoint },
      update: {
        codVendedor,
        idEmpresa,
        role,
        p256dh: dto.keys.p256dh,
        auth: dto.keys.auth,
      },
      create: {
        codVendedor,
        idEmpresa,
        role,
        endpoint: dto.endpoint,
        p256dh: dto.keys.p256dh,
        auth: dto.keys.auth,
      },
    });
  }

  // Escopado ao dono: só remove subscription do próprio usuário — quem souber o
  // endpoint de terceiro não consegue desregistrá-lo.
  async unsubscribe(userId: string, endpoint: string): Promise<void> {
    const prisma = this.cls.get('prisma');
    if (!prisma) throw new Error('prisma não disponível no CLS');
    const idEmpresa = this.cls.get('idEmpresa');
    const codVendedor = userId ? parseInt(userId, 10) : null;

    await prisma.pushSubscription.deleteMany({ where: { endpoint, idEmpresa, codVendedor } });
  }

  async pendingCount(userId: string, role: string): Promise<PendingCountResponse> {
    const prisma = this.cls.get('prisma');
    if (!prisma) throw new Error('prisma não disponível no CLS');
    const idEmpresa = this.cls.get('idEmpresa');

    if (role === 'supervisor' || role === 'manager' || role === 'admin') {
      const count = await prisma.pedido.count({
        where: { situa: SITUA_PENDENTE, idEmpresa },
      });
      return { count };
    }

    return { count: 0 };
  }

  // Envia push para todos os supervisores/managers/admin da empresa.
  async notifySupervisors(payload: PushPayload): Promise<void> {
    const prisma = this.cls.get('prisma');
    if (!prisma) return;
    const idEmpresa = this.cls.get('idEmpresa');

    const subs = await prisma.pushSubscription.findMany({
      where: {
        idEmpresa,
        role: { in: ['supervisor', 'manager', 'admin'] },
      },
    });

    await Promise.allSettled(subs.map((s) => this.push.send(s, payload)));
  }

  // Envia push para um codVendedor específico (todos os dispositivos registrados).
  async notifyUser(userId: string, payload: PushPayload): Promise<void> {
    const prisma = this.cls.get('prisma');
    if (!prisma) return;
    const idEmpresa = this.cls.get('idEmpresa');
    const codVendedor = parseInt(userId, 10);

    const subs = await prisma.pushSubscription.findMany({
      where: { idEmpresa, codVendedor },
    });
    await Promise.allSettled(subs.map((s) => this.push.send(s, payload)));
  }
}
