import { prisma, tenantDb } from '../src/config/database.js';

const yearMonth = '2025-02';
const contribuyenteId = 'd745a915-6a23-4818-944b-a7e1e18e536a';
const tenantRfc = 'DESPACHO_MO3NI6U8_B9VGG';

async function main() {
  const tenant = await prisma.tenant.findFirst({ where: { rfc: tenantRfc }, select: { id: true, databaseName: true } });
  if (!tenant) return;
  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')}`;

  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)`;

  // Drill desglosado por régimen del receptor
  const { rows } = await pool.query(
    `SELECT
       COALESCE(regimen_fiscal_receptor, 'null') AS regimen_rec,
       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')
       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 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 regimen_rec, type, tipo_comprobante, metodo_pago, tipo_rel
     ORDER BY regimen_rec, tipo_comprobante, metodo_pago`,
    [fi, ff, contribuyenteId],
  );

  const byReg: Record<string, { fact: number; pago: number; nc: number; detalle: any[] }> = {};
  for (const r of rows) {
    const reg = r.regimen_rec;
    if (!byReg[reg]) byReg[reg] = { fact: 0, pago: 0, nc: 0, detalle: [] };
    const v = r.tipo_comprobante === 'P' ? Number(r.pago_neto) : Number(r.total_neto);
    byReg[reg].detalle.push({ tc: r.tipo_comprobante, mp: r.metodo_pago, rel: r.tipo_rel, n: r.n, valor: v, bruto: Number(r.total_bruto) });
    if (r.tipo_comprobante === 'I') byReg[reg].fact += v;
    else if (r.tipo_comprobante === 'P') byReg[reg].pago += v;
    else if (r.tipo_comprobante === 'E') byReg[reg].nc += v;
  }

  console.log(`\n=== DRILL-DOWN por régimen del receptor — ${fi} a ${ff} ===\n`);
  let totalAll = 0;
  const TODOS_REGS = new Set(['605','606','612','621','625','626','601','603','607','608','610','611','614','615','620','622','623','624']);
  for (const [reg, v] of Object.entries(byReg).sort()) {
    const subtot = v.fact + v.pago - v.nc;
    totalAll += subtot;
    const inTodos = TODOS_REGS.has(reg) ? '✓' : '✗ (excluido de TODOS_REGIMENES)';
    console.log(`Régimen ${reg} ${inTodos}`);
    console.log(`  fact=${v.fact.toFixed(2)}  pago=${v.pago.toFixed(2)}  NC=${v.nc.toFixed(2)}  → subtotal=${subtot.toFixed(2)}`);
    for (const d of v.detalle) {
      console.log(`    ${d.tc} ${d.mp || '-'} rel=${d.rel || '-'}  n=${d.n}  bruto=${d.bruto.toFixed(2)}  neto=${d.valor.toFixed(2)}`);
    }
  }
  console.log(`\nTotal todos regímenes: ${totalAll.toFixed(2)}`);
  const inTodos = Object.entries(byReg).filter(([r]) => TODOS_REGS.has(r)).reduce((s, [, v]) => s + (v.fact + v.pago - v.nc), 0);
  console.log(`Total solo en TODOS_REGIMENES: ${inTodos.toFixed(2)}`);
  await prisma.$disconnect();
}
main().catch(async e => { console.error(e); await prisma.$disconnect().catch(() => {}); process.exit(1); });
