/**
 * One-shot: marca el origen de los movimientos de tesorería generados por
 * depósito/débito de cheques.
 *
 * Por qué: `tes-cheques.service.ts` creaba esos `tes_movimientos` sin
 * `origen_tipo`/`origen_id`, así que `TesMovimientosService.anular()` —que
 * bloquea la anulación suelta de todo movimiento con origen— los dejaba pasar.
 * Anular uno revertía el saldo pero dejaba el cheque en DEPOSITADO/DEBITADO
 * apuntando a un movimiento anulado: plata que no cuadra contra la cartera.
 * El servicio ya lo setea; esto cierra los que quedaron de antes.
 *
 * Idempotente: sólo toca movimientos con `origen_tipo IS NULL`. Los cheques que
 * cuelgan de un recibo/OP ya traen el origen de ese documento y no se tocan.
 *
 * Uso:
 *   pnpm exec ts-node scripts/backfill-origen-movimientos-cheque.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,
  };
}

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

  const cheques = await prisma.tes_cheques.findMany({
    where: {
      movimiento_id: { not: null },
      ...(args.empresa ? { empresa_id: args.empresa } : {}),
      movimiento: { origen_tipo: null },
    },
    select: {
      id: true,
      empresa_id: true,
      tipo: true,
      estado: true,
      numero_cheque: true,
      movimiento: { select: { id: true, tipo: true, estado: true, monto: true } },
    },
    orderBy: { created_at: 'asc' },
  });

  if (cheques.length === 0) {
    console.log('\nNo hay movimientos de cheque sin origen. Nada que hacer.\n');
    await prisma.$disconnect();
    return;
  }

  console.log(`\nMovimientos de cheque sin origen: ${cheques.length}\n`);

  // INGRESO → el cheque se depositó; EGRESO → se debitó. Se decide por el tipo
  // del movimiento y no por el del cheque: es el que refleja el efecto real
  // sobre el saldo, que es lo que la anulación revertiría.
  const plan = cheques.map((c) => ({
    chequeId: c.id,
    movimientoId: c.movimiento!.id,
    numero: c.numero_cheque,
    origen_tipo: c.movimiento!.tipo === 'INGRESO' ? 'CHEQUE_DEPOSITADO' : 'CHEQUE_DEBITADO',
  }));

  const resumen = plan.reduce<Record<string, number>>((acc, p) => {
    acc[p.origen_tipo] = (acc[p.origen_tipo] ?? 0) + 1;
    return acc;
  }, {});
  for (const [tipo, cant] of Object.entries(resumen)) console.log(`  ${tipo}: ${cant}`);

  if (!args.apply) {
    console.log('\nPrimeros 10:');
    for (const p of plan.slice(0, 10)) {
      console.log(`  cheque ${p.numero} → mov ${p.movimientoId} = ${p.origen_tipo}`);
    }
    console.log('\nDRY-RUN — no se escribieron cambios. Corré con --apply para aplicar.\n');
    await prisma.$disconnect();
    return;
  }

  let actualizados = 0;
  for (const p of plan) {
    // El filtro por origen_tipo null se repite en el update para que una corrida
    // concurrente no pise un origen ya escrito por el servicio.
    const r = await prisma.tes_movimientos.updateMany({
      where: { id: p.movimientoId, origen_tipo: null },
      data: { origen_tipo: p.origen_tipo, origen_id: p.chequeId },
    });
    actualizados += r.count;
  }

  console.log(`\nAPLICADO ✅ — ${actualizados} movimiento(s) marcados.\n`);
  await prisma.$disconnect();
}

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