/**
 * One-shot: pasa a DIFERIDO los cheques EN_CARTERA cuya fecha de vencimiento
 * todavía no llegó.
 *
 * Por qué: el alta manual de cheques (`TesChequeService.create`) fijaba siempre
 * EN_CARTERA sin mirar `fecha_vencimiento`, mientras recibos, pagos a proveedor
 * y rendiciones sí calculaban DIFERIDO. Como `assertOperable()` deja pasar
 * EN_CARTERA sin condición, esos cheques se podían depositar/debitar antes de
 * su fecha. El servicio ya lo calcula; esto corrige los que quedaron.
 *
 * El camino de vuelta ya existe y es automático: el cron diario (y ahora
 * también el arranque del backend) devuelve DIFERIDO → EN_CARTERA al vencer.
 *
 * Idempotente. Sólo toca EN_CARTERA con vencimiento futuro.
 *
 * Uso:
 *   pnpm exec ts-node scripts/backfill-cheques-diferidos.ts [--empresa=<id>] [--apply]
 *
 * Sin --apply → dry-run (default seguro).
 */
import 'dotenv/config';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

function parseArgs(argv: string[]) {
  const empresaArg = argv.find((a) => a.startsWith('--empresa='));
  return {
    apply: argv.includes('--apply'),
    empresa: empresaArg ? empresaArg.split('=')[1] : undefined,
  };
}

/** Hoy en hora local del servidor, a medianoche. Vence hoy = ya es operable. */
function inicioDeHoy(): Date {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  return d;
}

async function main() {
  const args = parseArgs(process.argv.slice(2));
  const hoy = inicioDeHoy();

  const candidatos = await prisma.tes_cheques.findMany({
    where: {
      estado: 'EN_CARTERA',
      fecha_vencimiento: { gt: hoy },
      ...(args.empresa ? { empresa_id: args.empresa } : {}),
    },
    select: {
      id: true,
      empresa_id: true,
      tipo: true,
      numero_cheque: true,
      monto: true,
      moneda: true,
      fecha_vencimiento: true,
    },
    orderBy: { fecha_vencimiento: 'asc' },
  });

  if (candidatos.length === 0) {
    console.log('\nNo hay cheques EN_CARTERA con vencimiento futuro. Nada que hacer.\n');
    await prisma.$disconnect();
    return;
  }

  console.log(`\nCheques EN_CARTERA con vencimiento futuro: ${candidatos.length}`);
  const porTipo = candidatos.reduce<Record<string, number>>((acc, c) => {
    acc[c.tipo] = (acc[c.tipo] ?? 0) + 1;
    return acc;
  }, {});
  for (const [tipo, cant] of Object.entries(porTipo)) console.log(`  ${tipo}: ${cant}`);

  if (!args.apply) {
    console.log('\nPrimeros 10:');
    for (const c of candidatos.slice(0, 10)) {
      const venc = c.fecha_vencimiento?.toISOString().slice(0, 10);
      console.log(`  ${c.tipo} Nº ${c.numero_cheque} — vence ${venc} — ${c.moneda} ${c.monto}`);
    }
    console.log('\nDRY-RUN — no se escribieron cambios. Corré con --apply para aplicar.\n');
    await prisma.$disconnect();
    return;
  }

  // Se repiten las condiciones en el updateMany para no pisar un cheque que
  // haya cambiado de estado entre la lectura y la escritura.
  const r = await prisma.tes_cheques.updateMany({
    where: {
      id: { in: candidatos.map((c) => c.id) },
      estado: 'EN_CARTERA',
      fecha_vencimiento: { gt: hoy },
    },
    data: { estado: 'DIFERIDO', updated_at: new Date() },
  });

  console.log(`\nAPLICADO ✅ — ${r.count} cheque(s) pasados a DIFERIDO.\n`);
  await prisma.$disconnect();
}

main()
  .then(() => process.exit(0))
  .catch((e) => {
    console.error('Falló el backfill:', e);
    process.exit(1);
  });
