/**
 * Script: fix-demo-carteras-asignaciones
 *
 * Corrige la estructura de carteras de Demo Ventas para que las asignaciones
 * de obligaciones/tareas al auxiliar sean válidas:
 *  - La cartera principal queda solo para el supervisor.
 *  - Se crea una subcartera asignada al auxiliar.
 *  - Los contribuyentes se mueven a la subcartera del auxiliar.
 *  - Se mantiene la relación auxiliar → supervisor.
 *
 * Ejecución:
 *   cd apps/api && npx tsx scripts/fix-demo-carteras-asignaciones.ts
 */
import { PrismaClient } from '@prisma/client';
import { tenantDb } from '../src/config/database.ts';

const prisma = new PrismaClient();
const DEMO_RFC = 'DEMO2501019X2';

async function main() {
  console.log('🔧 Corrigiendo carteras y asignaciones de Demo Ventas...\n');

  const tenant = await prisma.tenant.findUnique({ where: { rfc: DEMO_RFC } });
  if (!tenant) throw new Error(`Tenant ${DEMO_RFC} no encontrado`);

  const [supervisor, auxiliar] = await Promise.all([
    prisma.user.findUnique({ where: { email: 'supervisor@horuxfin.com' } }),
    prisma.user.findUnique({ where: { email: 'auxiliar@horuxfin.com' } }),
  ]);
  if (!supervisor) throw new Error('Usuario supervisor no encontrado');
  if (!auxiliar) throw new Error('Usuario auxiliar no encontrado');

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

  try {
    await client.query('BEGIN');

    // Obtener cartera principal
    const { rows: [carteraPrincipal] } = await client.query<{ id: string }>(`
      SELECT id FROM carteras WHERE parent_id IS NULL ORDER BY created_at LIMIT 1
    `);
    if (!carteraPrincipal) throw new Error('No existe cartera principal');

    // Crear subcartera para el auxiliar
    const { rows: [subcartera] } = await client.query<{ id: string }>(`
      INSERT INTO carteras (supervisor_user_id, auxiliar_user_id, nombre, descripcion, parent_id)
      VALUES ($1, $2, $3, $4, $5)
      ON CONFLICT DO NOTHING
      RETURNING id
    `, [supervisor.id, auxiliar.id, 'Cartera Auxiliar Demo', 'RFCs asignados al auxiliar de demo', carteraPrincipal.id]);

    const subcarteraId = subcartera?.id;
    if (!subcarteraId) {
      // Si ya existía, recuperarla
      const { rows: [existing] } = await client.query<{ id: string }>(`
        SELECT id FROM carteras WHERE parent_id = $1 AND auxiliar_user_id = $2 LIMIT 1
      `, [carteraPrincipal.id, auxiliar.id]);
      if (!existing) throw new Error('No se pudo crear ni recuperar la subcartera del auxiliar');
      // Asegurar que tenga supervisor
      await client.query(`UPDATE carteras SET supervisor_user_id = $1 WHERE id = $2`, [supervisor.id, existing.id]);
    }
    const finalSubcarteraId = subcarteraId || (await client.query<{ id: string }>(`SELECT id FROM carteras WHERE parent_id = $1 AND auxiliar_user_id = $2 LIMIT 1`, [carteraPrincipal.id, auxiliar.id])).rows[0].id;

    console.log('✅ Subcartera del auxiliar creada/recuperada');

    // Mover contribuyentes de la cartera principal a la subcartera del auxiliar
    const { rows: entidades } = await client.query<{ entidad_id: string }>(`
      SELECT entidad_id FROM cartera_entidades WHERE cartera_id = $1
    `, [carteraPrincipal.id]);

    for (const e of entidades) {
      await client.query(`
        INSERT INTO cartera_entidades (cartera_id, entidad_id)
        VALUES ($1, $2)
        ON CONFLICT DO NOTHING
      `, [finalSubcarteraId, e.entidad_id]);
    }

    // Quitar contribuyentes de la cartera principal (ahora están en la subcartera)
    await client.query(`DELETE FROM cartera_entidades WHERE cartera_id = $1`, [carteraPrincipal.id]);

    // La cartera principal ya no tiene auxiliar asignado
    await client.query(`UPDATE carteras SET auxiliar_user_id = NULL WHERE id = $1`, [carteraPrincipal.id]);

    await client.query('COMMIT');

    console.log(`✅ ${entidades.length} contribuyentes movidos a la subcartera del auxiliar`);
    console.log('✅ Cartera principal limpia (sin auxiliar)');

    // Asegurar relación auxiliar → supervisor
    await pool.query(`
      INSERT INTO auxiliar_supervisores (auxiliar_user_id, supervisor_user_id)
      VALUES ($1, $2)
      ON CONFLICT (auxiliar_user_id) DO UPDATE SET supervisor_user_id = EXCLUDED.supervisor_user_id
    `, [auxiliar.id, supervisor.id]);
    console.log('✅ Relación auxiliar → supervisor registrada');

    // Validar: el auxiliar debe ser elegible para todos los contribuyentes
    const { rows: elegibles } = await pool.query<{ entidad_id: string }>(`
      SELECT DISTINCT ce.entidad_id
        FROM carteras c
        JOIN cartera_entidades ce ON ce.cartera_id = c.id
       WHERE c.auxiliar_user_id = $1
    `, [auxiliar.id]);
    console.log(`✅ Auxiliar elegible para ${elegibles.length} contribuyentes`);

  } catch (err) {
    await client.query('ROLLBACK');
    throw err;
  } finally {
    client.release();
  }

  console.log('\n🎉 Estructura de carteras corregida');
}

main()
  .catch((e) => {
    console.error('\n❌ Error:', e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
    await tenantDb.shutdown();
  });
