/**
 * Backfill one-shot: completa los campos de emisor/subtotal/IVA/XML en las
 * filas de `cfdis` con `source='facturapi'` que fueron insertadas por la
 * versión buggy del controller (previo al fix 2026-04-24).
 *
 * Descarga el XML real de Facturapi, lo parsea con el mismo parser SAT,
 * upsertea la fila de `rfcs` del emisor, y actualiza la fila de `cfdis`.
 */
import { prisma, tenantDb } from '../src/config/database.js';
import { downloadXmlContribuyente } from '../src/services/contribuyente-facturapi.service.js';
import * as facturapiService from '../src/services/facturapi.service.js';
import { parseXml } from '../src/services/sat/sat-parser.service.js';

const TENANT_RFC = process.argv[2] || 'DESPACHO_MO3NI6U8_B9VGG';

async function main() {
  const tenant = await prisma.tenant.findFirst({
    where: { rfc: TENANT_RFC },
    select: { id: true, databaseName: true },
  });
  if (!tenant) {
    console.log(`Tenant ${TENANT_RFC} no encontrado`);
    return;
  }
  const pool = await tenantDb.getPool(tenant.id, tenant.databaseName);

  const { rows: pendientes } = await pool.query<{
    id: number;
    uuid: string;
    facturapi_id: string;
    contribuyente_id: string | null;
    rfc_emisor: string | null;
  }>(
    `SELECT id, uuid, facturapi_id, contribuyente_id, rfc_emisor
       FROM cfdis
      WHERE source = 'facturapi'
        AND (COALESCE(rfc_emisor, '') = '' OR xml_original IS NULL OR subtotal = 0)
      ORDER BY fecha_emision ASC`,
  );

  console.log(`Encontradas ${pendientes.length} CFDIs Facturapi a backfillear en ${TENANT_RFC}\n`);

  let ok = 0;
  let fail = 0;

  for (const row of pendientes) {
    try {
      console.log(`\n[${row.uuid}] facturapi_id=${row.facturapi_id} contrib=${row.contribuyente_id}`);

      const xmlBuffer = row.contribuyente_id
        ? await downloadXmlContribuyente(pool, row.contribuyente_id, row.facturapi_id)
        : await facturapiService.downloadXml(tenant.id, row.facturapi_id);
      const xmlString = xmlBuffer.toString('utf-8');
      const parsed = parseXml(xmlString, 'emitidos');
      if (!parsed) {
        console.log(`  ⚠️  Parser retornó null — skip`);
        fail++;
        continue;
      }

      console.log(`  emisor=${parsed.rfcEmisor} (${parsed.nombreEmisor}, régimen ${parsed.regimenFiscalEmisor})`);
      console.log(`  receptor=${parsed.rfcReceptor} (${parsed.nombreReceptor}, régimen ${parsed.regimenFiscalReceptor})`);
      console.log(`  subtotal=${parsed.subtotal} total=${parsed.total} iva_traslado=${parsed.ivaTraslado}`);

      // Upsert rfcs emisor
      const { rows: [emisorRow] } = await pool.query(
        `INSERT INTO rfcs (rfc, razon_social, regimen_fiscal) VALUES ($1, $2, $3)
         ON CONFLICT (rfc) DO UPDATE SET
           razon_social = COALESCE(NULLIF($2, ''), rfcs.razon_social),
           regimen_fiscal = CASE WHEN $3 IS NOT NULL AND $3 != '' THEN $3 ELSE rfcs.regimen_fiscal END
         RETURNING id`,
        [parsed.rfcEmisor, parsed.nombreEmisor || null, parsed.regimenFiscalEmisor || null],
      );
      // Upsert rfcs receptor
      const { rows: [receptorRow] } = await pool.query(
        `INSERT INTO rfcs (rfc, razon_social, regimen_fiscal) VALUES ($1, $2, $3)
         ON CONFLICT (rfc) DO UPDATE SET
           razon_social = COALESCE(NULLIF($2, ''), rfcs.razon_social),
           regimen_fiscal = CASE WHEN $3 IS NOT NULL AND $3 != '' THEN $3 ELSE rfcs.regimen_fiscal END
         RETURNING id`,
        [parsed.rfcReceptor, parsed.nombreReceptor || null, parsed.regimenFiscalReceptor || null],
      );

      await pool.query(
        `UPDATE cfdis SET
           fecha_cert_sat = $2,
           rfc_emisor_id = $3, rfc_emisor = $4, nombre_emisor = $5,
           regimen_fiscal_emisor = $6,
           rfc_receptor_id = $7, rfc_receptor = $8, nombre_receptor = $9,
           regimen_fiscal_receptor = $10,
           subtotal = $11, subtotal_mxn = $11,
           total = $12, total_mxn = $12,
           iva_traslado = $13, iva_traslado_mxn = $13,
           iva_retencion = $14, iva_retencion_mxn = $14,
           xml_original = $15,
           serie = COALESCE($16, serie), folio = COALESCE($17, folio)
         WHERE id = $1`,
        [
          row.id,
          parsed.fechaCertSat,
          emisorRow.id, parsed.rfcEmisor, parsed.nombreEmisor,
          parsed.regimenFiscalEmisor,
          receptorRow.id, parsed.rfcReceptor, parsed.nombreReceptor,
          parsed.regimenFiscalReceptor,
          parsed.subtotal,
          parsed.total,
          parsed.ivaTraslado,
          parsed.ivaRetencion,
          xmlString,
          parsed.serie, parsed.folio,
        ],
      );

      console.log(`  ✅ actualizada fila id=${row.id}`);
      ok++;
    } catch (e: any) {
      console.log(`  ❌ error: ${e?.message || String(e)}`);
      fail++;
    }
  }

  console.log(`\n=== Resumen: ${ok} actualizadas, ${fail} fallidas ===`);
  await prisma.$disconnect();
}

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