/**
 * Recalcula el monto_base y monto_comision de comisiones de VENTA en estado
 * 'pendiente' descontando las NC aplicadas a la factura (factura_cab.total_notas_credito).
 *
 * Idempotente: solo actualiza filas donde el monto cambia. Si la nueva base
 * resulta ≤ 0, cancela la comisión.
 *
 * Uso:
 *   pnpm exec ts-node scripts/recalcular-comisiones-venta-nc.ts [--empresa=<id>] [--dry]
 */
import 'dotenv/config';
import { PrismaClient, Prisma } from '@prisma/client';

type Args = { empresaId?: string; dry: boolean };

function parseArgs(argv: string[]): Args {
  const out: Args = { dry: false };
  for (const a of argv.slice(2)) {
    if (a === '--dry') out.dry = true;
    else if (a.startsWith('--empresa=')) out.empresaId = a.split('=')[1];
  }
  return out;
}

async function main() {
  const { empresaId, dry } = parseArgs(process.argv);
  const prisma = new PrismaClient();

  const where: Prisma.comisionesWhereInput = {
    tipo: 'venta',
    estado: 'pendiente',
    factura_id: { not: null },
  };
  if (empresaId) where.empresa_id = empresaId;

  const comisiones = await prisma.comisiones.findMany({
    where,
    include: {
      factura_cab: {
        select: {
          id: true,
          total_notas_credito: true,
          factura_subtotales: { select: { dtotope: true }, take: 1 },
        },
      },
    },
  });

  console.log(`Comisiones venta pendientes encontradas: ${comisiones.length}`);

  let updated = 0;
  let canceladas = 0;
  let sinCambio = 0;

  for (const c of comisiones) {
    if (!c.factura_cab) {
      sinCambio++;
      continue;
    }
    const montoBruto = Number(c.factura_cab.factura_subtotales?.[0]?.dtotope ?? 0);
    const totalNc = Number(c.factura_cab.total_notas_credito ?? 0);
    const nuevaBase = montoBruto - totalNc;

    const pct = c.porcentaje_aplicado ? Number(c.porcentaje_aplicado) : 0;
    const fijo = c.monto_fijo_aplicado ? Number(c.monto_fijo_aplicado) : 0;

    const baseActual = Number(c.monto_base);
    if (Math.abs(baseActual - nuevaBase) < 0.01) {
      sinCambio++;
      continue;
    }

    if (nuevaBase <= 0) {
      console.log(
        `  Cancelando comisión ${c.id} | factura=${c.factura_id} | base ${baseActual} → ${nuevaBase} (NC=${totalNc})`,
      );
      if (!dry) {
        await prisma.comisiones.update({
          where: { id: c.id },
          data: {
            estado: 'cancelada',
            observaciones: `Cancelada por NC posterior. Base bruta=${montoBruto}, NC=${totalNc}.`,
            updated_at: new Date(),
          },
        });
      }
      canceladas++;
      continue;
    }

    const nuevaComision = (nuevaBase * pct) / 100 + fijo;
    console.log(
      `  Actualizando ${c.id} | base ${baseActual} → ${nuevaBase} (NC=${totalNc}) | comisión ${Number(c.monto_comision)} → ${nuevaComision}`,
    );
    if (!dry) {
      await prisma.comisiones.update({
        where: { id: c.id },
        data: {
          monto_base: new Prisma.Decimal(nuevaBase),
          monto_comision: new Prisma.Decimal(nuevaComision),
          observaciones: c.observaciones
            ? `${c.observaciones} | Recalculada con NC=${totalNc}`
            : `Recalculada con NC=${totalNc}`,
          updated_at: new Date(),
        },
      });
    }
    updated++;
  }

  console.log('─'.repeat(60));
  console.log(`Total revisadas: ${comisiones.length}`);
  console.log(`Sin cambios:     ${sinCambio}`);
  console.log(`Actualizadas:    ${updated}`);
  console.log(`Canceladas:      ${canceladas}`);
  console.log(dry ? '(DRY-RUN — no se persistió nada)' : '✔ Persistido.');

  await prisma.$disconnect();
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});
