#!/usr/bin/env node
/**
 * Script para actualizar CFDIs existentes con su XML original
 * Uso: node scripts/update-cfdi-xml.js <directorio> <schema>
 * Ejemplo: node scripts/update-cfdi-xml.js /root/xmls tenant_roem691011ez4
 */

const fs = require('fs');
const path = require('path');
const { Pool } = require('pg');

// Configuración de la base de datos
const pool = new Pool({
  host: 'localhost',
  port: 5432,
  database: 'horux360',
  user: 'postgres',
  password: 'postgres',
});

// Extraer UUID del XML
function extractUuidFromXml(xmlContent) {
  // Buscar UUID en TimbreFiscalDigital
  const uuidMatch = xmlContent.match(/UUID=["']([A-Fa-f0-9-]{36})["']/i);
  return uuidMatch ? uuidMatch[1].toUpperCase() : null;
}

// Procesar archivos en lotes
async function processFiles(directory, schema, batchSize = 500) {
  const files = fs.readdirSync(directory).filter(f => f.toLowerCase().endsWith('.xml'));

  console.log(`\nEncontrados ${files.length} archivos XML en ${directory}`);
  console.log(`Schema: ${schema}`);
  console.log(`Tamaño de lote: ${batchSize}\n`);

  let updated = 0;
  let notFound = 0;
  let errors = 0;
  let processed = 0;

  const startTime = Date.now();

  // Procesar en lotes
  for (let i = 0; i < files.length; i += batchSize) {
    const batch = files.slice(i, i + batchSize);
    const updates = [];

    // Leer y parsear XMLs del lote
    for (const file of batch) {
      try {
        const filePath = path.join(directory, file);
        const xmlContent = fs.readFileSync(filePath, 'utf8');
        const uuid = extractUuidFromXml(xmlContent);

        if (uuid) {
          updates.push({ uuid, xmlContent });
        } else {
          errors++;
          if (errors <= 5) {
            console.log(`  ⚠ No se encontró UUID en: ${file}`);
          }
        }
      } catch (err) {
        errors++;
        if (errors <= 5) {
          console.log(`  ✗ Error leyendo ${file}: ${err.message}`);
        }
      }
    }

    // Actualizar base de datos en una transacción
    const client = await pool.connect();
    try {
      await client.query('BEGIN');

      for (const { uuid, xmlContent } of updates) {
        const result = await client.query(
          `UPDATE "${schema}".cfdis SET xml_original = $1 WHERE UPPER(uuid_fiscal) = $2 AND xml_original IS NULL`,
          [xmlContent, uuid]
        );

        if (result.rowCount > 0) {
          updated++;
        } else {
          notFound++;
        }
      }

      await client.query('COMMIT');
    } catch (err) {
      await client.query('ROLLBACK');
      console.error(`Error en lote: ${err.message}`);
      errors += batch.length;
    } finally {
      client.release();
    }

    processed += batch.length;

    // Progreso
    const percent = ((processed / files.length) * 100).toFixed(1);
    const elapsed = ((Date.now() - startTime) / 1000).toFixed(0);
    const rate = (processed / elapsed).toFixed(0);
    process.stdout.write(`\r  Procesando: ${processed}/${files.length} (${percent}%) - ${updated} actualizados - ${rate} archivos/seg    `);
  }

  const totalTime = ((Date.now() - startTime) / 1000).toFixed(1);

  console.log(`\n\n✓ Completado en ${totalTime} segundos`);
  console.log(`  - Actualizados: ${updated}`);
  console.log(`  - No encontrados (UUID no existe en BD): ${notFound}`);
  console.log(`  - Errores: ${errors}`);

  await pool.end();
}

// Main
const args = process.argv.slice(2);
if (args.length < 2) {
  console.log('Uso: node scripts/update-cfdi-xml.js <directorio> <schema>');
  console.log('Ejemplo: node scripts/update-cfdi-xml.js /root/xmls tenant_roem691011ez4');
  process.exit(1);
}

const [directory, schema] = args;

if (!fs.existsSync(directory)) {
  console.error(`Error: El directorio ${directory} no existe`);
  process.exit(1);
}

processFiles(directory, schema).catch(err => {
  console.error('Error fatal:', err);
  process.exit(1);
});
