/**
 * Backfill de métricas mensuales pre-calculadas (Tanda A hot/cold).
 *
 * Itera todos los tenants activos, sus contribuyentes, y popula la tabla
 * `metricas_mensuales` con los agregados de años pasados (desde el CFDI más
 * antiguo hasta el año actual - 1). El año actual queda on-the-fly.
 *
 * Idempotente: usa upsert — re-correrlo no duplica filas, recalcula valores.
 *
 * Uso:
 *   pnpm --filter @horux/api exec tsx scripts/backfill-metricas.ts          # ejecuta
 *   pnpm --filter @horux/api exec tsx scripts/backfill-metricas.ts --dry    # dry-run
 *
 * Opciones via env:
 *   BACKFILL_DESDE_ANIO=2023   # limita el rango inferior
 *   BACKFILL_HASTA_ANIO=2024   # default: año actual - 1
 *   BACKFILL_TENANT=<uuid>     # procesa solo un tenant
 */
import { prisma } from '../src/config/database.js';
import { backfillTenant } from '../src/services/metricas-compute.service.js';

const DRY_RUN = process.argv.includes('--dry') || process.argv.includes('--dry-run');
const TENANT_FILTER = process.env.BACKFILL_TENANT || null;
const DESDE_ANIO = process.env.BACKFILL_DESDE_ANIO ? parseInt(process.env.BACKFILL_DESDE_ANIO, 10) : undefined;
const HASTA_ANIO = process.env.BACKFILL_HASTA_ANIO ? parseInt(process.env.BACKFILL_HASTA_ANIO, 10) : undefined;

async function main() {
  console.log(`=== Backfill metricas_mensuales ${DRY_RUN ? '(DRY RUN)' : ''} ===\n`);
  if (DESDE_ANIO) console.log(`Desde año: ${DESDE_ANIO}`);
  if (HASTA_ANIO) console.log(`Hasta año: ${HASTA_ANIO}`);
  if (TENANT_FILTER) console.log(`Tenant filtro: ${TENANT_FILTER}`);
  console.log();

  const tenants = await prisma.tenant.findMany({
    where: {
      active: true,
      ...(TENANT_FILTER ? { id: TENANT_FILTER } : {}),
    },
    select: { id: true, rfc: true, nombre: true },
    orderBy: { rfc: 'asc' },
  });

  console.log(`Tenants activos: ${tenants.length}\n`);

  let totalContribs = 0;
  let totalMeses = 0;
  let totalFilas = 0;
  let totalErrores = 0;

  for (const t of tenants) {
    process.stdout.write(`[${t.rfc}] ${t.nombre} ... `);
    try {
      const r = await backfillTenant(t.id, {
        dryRun: DRY_RUN,
        desdeAnio: DESDE_ANIO,
        hastaAnio: HASTA_ANIO,
      });
      if (r.contribuyentesProcesados === 0) {
        console.log('sin contribuyentes (skip)');
      } else {
        console.log(
          `${r.contribuyentesProcesados} contribs, ${r.mesesProcesados} meses, ` +
          `${r.filasEscritas} filas${r.errores.length > 0 ? `, ${r.errores.length} errores` : ''}`,
        );
        if (r.errores.length > 0 && r.errores.length <= 5) {
          for (const e of r.errores) {
            console.log(`    ERR (${e.anio}-${String(e.mes).padStart(2, '0')}): ${e.error}`);
          }
        } else if (r.errores.length > 5) {
          console.log(`    (${r.errores.length} errores — los primeros 3):`);
          for (const e of r.errores.slice(0, 3)) {
            console.log(`    ERR (${e.anio}-${String(e.mes).padStart(2, '0')}): ${e.error}`);
          }
        }
      }
      totalContribs += r.contribuyentesProcesados;
      totalMeses += r.mesesProcesados;
      totalFilas += r.filasEscritas;
      totalErrores += r.errores.length;
    } catch (err: any) {
      console.log(`FATAL: ${err?.message || err}`);
      totalErrores++;
    }
  }

  console.log(`\n=== Resumen ===`);
  console.log(`  Tenants procesados:     ${tenants.length}`);
  console.log(`  Contribuyentes:         ${totalContribs}`);
  console.log(`  (Contribuyente, mes):   ${totalMeses}`);
  console.log(`  Filas metricas_mensuales: ${totalFilas}${DRY_RUN ? ' (NO escritas)' : ''}`);
  if (totalErrores > 0) console.log(`  Errores:               ${totalErrores}`);

  await prisma.$disconnect();
  process.exit(totalErrores > 0 ? 1 : 0);
}

main().catch(async (err) => {
  console.error('Fatal:', err);
  await prisma.$disconnect().catch(() => {});
  process.exit(1);
});
