import { ForbiddenException, Injectable } from '@nestjs/common';
import { ClsService } from 'nestjs-cls';
import type { EquipeResponse } from '@sar/api-interface';
import type { WorkspaceClsStore } from '../workspace/workspace.types';

function matrizEmpresa(idEmpresa: number): number {
  return idEmpresa > 9000 ? idEmpresa - 9000 : idEmpresa;
}

interface RepRow {
  cod_vendedor: number;
  nome: string | null;
}

interface PedidosRepRow {
  cod_vendedor: number;
  pedidos: string;
  faturamento: string;
}

interface MetaRepRow {
  cod_vendedor: number;
  meta_valor: string;
}

@Injectable()
export class EquipeService {
  constructor(private readonly cls: ClsService<WorkspaceClsStore>) {}

  async listEquipe(): Promise<EquipeResponse> {
    const role = this.cls.get('role') ?? 'rep';
    if (role !== 'manager' && role !== 'admin') {
      throw new ForbiddenException('Apenas gerentes podem consultar a equipe');
    }

    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 idEmpresaMatriz = matrizEmpresa(idEmpresa);

    const now = new Date();
    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const monthStartStr = new Date(year, month - 1, 1).toISOString().slice(0, 10);
    const monthEndStr = new Date(year, month, 0).toISOString().slice(0, 10);

    const [repRows, pedidosRows, metaRows] = await Promise.all([
      prisma.$queryRawUnsafe<RepRow[]>(
        `SELECT codigo AS cod_vendedor, nome FROM vw_representantes ORDER BY nome`,
      ),
      prisma.$queryRawUnsafe<PedidosRepRow[]>(`
        SELECT cod_vendedor,
               COUNT(*)::text                         AS pedidos,
               COALESCE(SUM(total), 0)::text          AS faturamento
        FROM vw_pedidos_erp
        WHERE id_empresa = ${idEmpresa}
          AND situa      NOT IN (1, 5)
          AND dt_pedido >= '${monthStartStr}'
          AND dt_pedido <= '${monthEndStr}'
        GROUP BY cod_vendedor
      `),
      prisma.$queryRawUnsafe<MetaRepRow[]>(`
        SELECT cod_vendedor,
               SUM(valor)::text AS meta_valor
        FROM sar.vw_metas
        WHERE id_empresa = ${idEmpresaMatriz}
          AND ano        = ${year}
          AND mes        = ${month}
          AND TRIM(tipo) = 'GR'
        GROUP BY cod_vendedor
      `),
    ]);

    const pedidosMap = new Map(
      pedidosRows.map((r) => [
        Number(r.cod_vendedor),
        { pedidos: Number(r.pedidos), faturamento: Number(r.faturamento) },
      ]),
    );
    const metaMap = new Map(metaRows.map((r) => [Number(r.cod_vendedor), Number(r.meta_valor)]));

    // vw_representantes pode retornar duplicatas por cod_vendedor — deduplicar
    const seenCods = new Set<number>();
    const uniqueReps = repRows.filter((r) => {
      const cod = Number(r.cod_vendedor);
      if (seenCods.has(cod)) return false;
      seenCods.add(cod);
      return true;
    });

    const reps = uniqueReps.map((r) => {
      const cod = Number(r.cod_vendedor);
      const stats = pedidosMap.get(cod);
      const meta = metaMap.get(cod) ?? 0;
      const faturamento = stats?.faturamento ?? 0;
      const pedidos = stats?.pedidos ?? 0;
      return {
        codVendedor: cod,
        nomeVendedor: r.nome ?? null,
        pedidosMes: pedidos,
        faturamentoMes: faturamento,
        ticketMedio: pedidos > 0 ? faturamento / pedidos : 0,
        pctMeta: meta > 0 ? Math.round((faturamento / meta) * 100) : 0,
      };
    });

    return {
      reps,
      totalReps: reps.length,
      syncedAt: now.toISOString(),
    };
  }
}
