/**
 * Compara Gastos del Dashboard vs Drill-down para un mes/contribuyente.
 * Identifica discrepancias y rompe el detalle por lado (factura/pago/NC).
 *
 * Uso: tsx scripts/validate-gastos.ts <tenantRfc> <entidadId> <añoMes>
 */
import { prisma, tenantDb } from '../src/config/database.js';
import { calcularEgresosPorRegimen } from '../src/services/dashboard.service.js';

const tenantRfcArg = process.argv[2] || 'DESPACHO_MO3NI6U8_B9VGG';
const contribuyenteId = process.argv[3] || 'd745a915-6a23-4818-944b-a7e1e18e536a';
const yearMonth = process.argv[4] || '2025-02';

async function main() {
  const tenant = await prisma.tenant.findFirst({
    where: { rfc: tenantRfcArg, active: true },
    select: { id: true, rfc: true, databaseName: true },
  });
  if (!tenant) { console.error('Tenant not found'); process.exit(1); }

  const pool = await tenantDb.getPool(tenant.id, tenant.databaseName);

  const [anio, mes] = yearMonth.split('-').map(Number);
  const lastDay = new Date(anio, mes, 0).getDate();
  const fi = `${yearMonth}-01`;
  const ff = `${yearMonth}-${String(lastDay).padStart(2, '0')}`;

  console.log(`\n=== Contribuyente ${contribuyenteId} — ${fi} a ${ff} ===\n`);

  // 1. Dashboard (calcularEgresosPorRegimen)
  const dashboard = await calcularEgresosPorRegimen(
    pool, tenant.id, fi, ff, undefined, undefined, false, contribuyenteId,
  );
  console.log('DASHBOARD calcularEgresosPorRegimen:');
  console.log(`  total: ${dashboard.total.toFixed(2)}`);
  for (const r of dashboard.porRegimen) {
    console.log(`    ${r.regimenClave} (${r.regimenDescripcion}): ${r.monto.toFixed(2)}`);
  }

  // 2. Drill-down query (simulated — bucket=gastos uniforme)
  const IMP_TRAS = `COALESCE(iva_traslado_mxn,0) + COALESCE(ieps_traslado_mxn,0) + COALESCE(impuestos_locales_trasladado_mxn,0)`;
  const IMP_TRAS_PAGO = `COALESCE(iva_traslado_pago_mxn,0) + COALESCE(ieps_traslado_pago_mxn,0)`;
  const EXCL_MONTO = `COALESCE((SELECT SUM(COALESCE(cc.importe_mxn,0) - COALESCE(cc.descuento_mxn,0)) FROM cfdi_conceptos cc WHERE cc.cfdi_id = cfdis.id AND cc.clave_prod_serv IN ('84121603','93161608','85101501','85121800')), 0)`;

  // bucket=gastos: RECIBIDO I PUE + RECIBIDO P + RECIBIDO E PUE (excl 07)
  // Sumamos tomando en cuenta el signo (E resta)
  const { rows: drillRows } = await pool.query(
    `SELECT
       type, tipo_comprobante, metodo_pago,
       COALESCE(cfdi_tipo_relacion, '') AS tipo_rel,
       COUNT(*)::int AS n,
       SUM(total_mxn) AS total_bruto,
       SUM(COALESCE(total_mxn,0) - (${IMP_TRAS}) - (${EXCL_MONTO})) AS total_neto,
       SUM(COALESCE(monto_pago_mxn,0) - (${IMP_TRAS_PAGO})) AS pago_neto
     FROM cfdis
     WHERE (
       (type = 'RECIBIDO' AND tipo_comprobante = 'I' AND metodo_pago = 'PUE'
           AND COALESCE(cfdi_tipo_relacion, '') <> '07')
       OR (type = 'RECIBIDO' AND tipo_comprobante = 'P')
       OR (type = 'RECIBIDO' AND tipo_comprobante = 'E' AND metodo_pago = 'PUE'
           AND COALESCE(cfdi_tipo_relacion, '') <> '07')
     )
     AND regimen_fiscal_receptor IN ('605','606','612','621','625','626','601','603','607','608','610','611','614','615','620','622','623','624')
     AND status NOT IN ('Cancelado','0')
     AND ((tipo_comprobante='P' AND fecha_pago_p >= $1::date AND fecha_pago_p < ($2::date + interval '1 day'))
       OR (tipo_comprobante!='P' AND fecha_emision >= $1::date AND fecha_emision < ($2::date + interval '1 day')))
     AND contribuyente_id = $3
     GROUP BY type, tipo_comprobante, metodo_pago, tipo_rel
     ORDER BY tipo_comprobante, metodo_pago`,
    [fi, ff, contribuyenteId],
  );

  console.log(`\nDRILL-DOWN bucket=gastos (filas del drill por bucket):`);
  let drillSumaFacturas = 0, drillSumaPagos = 0, drillSumaNC = 0;
  for (const r of drillRows) {
    const tc = r.tipo_comprobante;
    const valor = tc === 'P' ? Number(r.pago_neto) : Number(r.total_neto);
    console.log(`  ${r.type} ${tc} ${r.metodo_pago || '-'} rel=${r.tipo_rel || '-'}  n=${r.n}  total_bruto=${Number(r.total_bruto).toFixed(2)}  valor_neto=${valor.toFixed(2)}`);
    if (tc === 'I') drillSumaFacturas += valor;
    else if (tc === 'P') drillSumaPagos += valor;
    else if (tc === 'E') drillSumaNC += valor;
  }
  const drillTotal = drillSumaFacturas + drillSumaPagos - drillSumaNC;
  console.log(`  → facturas=${drillSumaFacturas.toFixed(2)}  pagos=${drillSumaPagos.toFixed(2)}  NC=${drillSumaNC.toFixed(2)}`);
  console.log(`  → drill total = ${drillTotal.toFixed(2)}`);

  // 3. Comparación
  const delta = dashboard.total - drillTotal;
  console.log(`\n=== COMPARATIVA ===`);
  console.log(`  Dashboard:     ${dashboard.total.toFixed(2)}`);
  console.log(`  Drill-down:    ${drillTotal.toFixed(2)}`);
  console.log(`  Delta:         ${delta.toFixed(2)}`);

  if (Math.abs(delta) < 0.01) {
    console.log(`  ✓ CUADRAN`);
  } else {
    console.log(`  ✗ NO CUADRAN — investigar`);
  }

  // 4. Régimenes del receptor que aparecen vs los ignorados
  const { rows: regsReceptor } = await pool.query(
    `SELECT DISTINCT regimen_fiscal_receptor
       FROM cfdis
      WHERE contribuyente_id = $1
        AND type = 'RECIBIDO'
        AND fecha_emision >= $2::date AND fecha_emision < ($3::date + interval '1 day')
      ORDER BY regimen_fiscal_receptor`,
    [contribuyenteId, fi, ff],
  );
  console.log(`\nRegímenes en CFDIs RECIBIDOS del periodo:`, regsReceptor.map(r => r.regimen_fiscal_receptor).join(', '));

  await prisma.$disconnect();
}

main().catch(async e => { console.error(e); await prisma.$disconnect().catch(() => {}); process.exit(1); });
