import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcryptjs';
import { Pool } from 'pg';
import { migrate } from '../src/config/tenant-migrations.js';
import { RESICO_TASAS, ISR_TARIFAS } from './isr-data.js';
import { EVENTOS_FISCALES, DIAS_INHABILES } from './eventos-fiscales-data.js';
import {
  FORMAS_PAGO, METODOS_PAGO, USOS_CFDI, MONEDAS, CLAVES_UNIDAD,
  OBJETOS_IMP, TIPOS_RELACION, EXPORTACIONES,
} from './catalogos-sat-data.js';

const prisma = new PrismaClient();

function parseDatabaseUrl(url: string) {
  const parsed = new URL(url);
  return {
    host: parsed.hostname,
    port: parseInt(parsed.port || '5432'),
    user: decodeURIComponent(parsed.username),
    password: decodeURIComponent(parsed.password),
  };
}

const REGIMENES_SAT = [
  { clave: '601', descripcion: 'General de Ley Personas Morales', tipoPersona: 'moral' },
  { clave: '603', descripcion: 'Personas Morales con Fines no Lucrativos', tipoPersona: 'moral' },
  { clave: '605', descripcion: 'Sueldos y Salarios e Ingresos Asimilados a Salarios', tipoPersona: 'fisica' },
  { clave: '606', descripcion: 'Arrendamiento', tipoPersona: 'fisica' },
  { clave: '607', descripcion: 'Régimen de Enajenación o Adquisición de Bienes', tipoPersona: 'fisica' },
  { clave: '608', descripcion: 'Demás ingresos', tipoPersona: 'fisica' },
  { clave: '610', descripcion: 'Residentes en el Extranjero sin Establecimiento Permanente en México', tipoPersona: 'ambos' },
  { clave: '611', descripcion: 'Ingresos por Dividendos (socios y accionistas)', tipoPersona: 'fisica' },
  { clave: '612', descripcion: 'Personas Físicas con Actividades Empresariales y Profesionales', tipoPersona: 'fisica' },
  { clave: '614', descripcion: 'Ingresos por intereses', tipoPersona: 'fisica' },
  { clave: '615', descripcion: 'Régimen de los ingresos por obtención de premios', tipoPersona: 'fisica' },
  { clave: '616', descripcion: 'Sin obligaciones fiscales', tipoPersona: 'ambos' },
  { clave: '620', descripcion: 'Sociedades Cooperativas de Producción que optan por diferir sus ingresos', tipoPersona: 'moral' },
  { clave: '621', descripcion: 'Incorporación Fiscal', tipoPersona: 'fisica' },
  { clave: '622', descripcion: 'Actividades Agrícolas, Ganaderas, Silvícolas y Pesqueras', tipoPersona: 'ambos' },
  { clave: '623', descripcion: 'Opcional para Grupos de Sociedades', tipoPersona: 'moral' },
  { clave: '624', descripcion: 'Coordinados', tipoPersona: 'moral' },
  { clave: '625', descripcion: 'Régimen de las Actividades Empresariales con ingresos a través de Plataformas Tecnológicas', tipoPersona: 'fisica' },
  { clave: '626', descripcion: 'Régimen Simplificado de Confianza', tipoPersona: 'ambos' },
];

async function main() {
  console.log('🌱 Seeding database...');

  // Seed regimenes catalog
  for (const r of REGIMENES_SAT) {
    await prisma.regimen.upsert({
      where: { clave: r.clave },
      update: { descripcion: r.descripcion, tipoPersona: r.tipoPersona },
      create: r,
    });
  }
  console.log(`✅ ${REGIMENES_SAT.length} regímenes fiscales SAT cargados`);

  // Seed ISR tables — limpiar y recrear
  await prisma.isrResicoTasa.deleteMany();
  await prisma.isrTarifa.deleteMany();

  for (const anio of [2020, 2021, 2022, 2023, 2024, 2025, 2026]) {
    if (anio >= 2022) {
      await prisma.isrResicoTasa.createMany({
        data: RESICO_TASAS.map(t => ({ anio, montoMaximo: t.montoMaximo, porcentaje: t.porcentaje })),
      });
    }

    const tarifas = ISR_TARIFAS[anio];
    if (tarifas) {
      await prisma.isrTarifa.createMany({
        data: tarifas.map(t => ({
          anio,
          limiteInferior: t.li,
          limiteSuperior: t.ls,
          cuotaFija: t.cf,
          porcentajeExcedente: t.pe,
        })),
      });
    }
  }
  console.log('✅ Tablas ISR 2020-2026 cargadas');

  // Seed eventos fiscales catálogo
  await prisma.eventoFiscalCatalogo.deleteMany();
  await prisma.eventoFiscalCatalogo.createMany({
    data: EVENTOS_FISCALES.map(e => ({
      titulo: e.titulo,
      tipo: e.tipo,
      diaBase: e.diaBase,
      mesRelativo: e.mesRelativo,
      mesFijo: (e as any).mesFijo || null,
      recurrencia: e.recurrencia,
      usaExtensionRfc: e.usaExtensionRfc,
      regimenes: e.regimenes,
      condicion: e.condicion || null,
    })),
  });
  console.log(`✅ ${EVENTOS_FISCALES.length} eventos fiscales cargados`);

  // Seed días inhábiles
  await prisma.diaInhabil.deleteMany();
  await prisma.diaInhabil.createMany({
    data: DIAS_INHABILES.map(d => ({ fecha: new Date(d.fecha), nombre: d.nombre })),
    skipDuplicates: true,
  });
  console.log(`✅ ${DIAS_INHABILES.length} días inhábiles cargados (2020-2027)`);

  // Seed catálogos SAT para facturación
  for (const fp of FORMAS_PAGO) {
    await prisma.catFormaPago.upsert({ where: { clave: fp.clave }, update: { descripcion: fp.descripcion }, create: fp });
  }
  console.log(`✅ ${FORMAS_PAGO.length} formas de pago cargadas`);

  for (const mp of METODOS_PAGO) {
    await prisma.catMetodoPago.upsert({ where: { clave: mp.clave }, update: { descripcion: mp.descripcion }, create: mp });
  }
  console.log(`✅ ${METODOS_PAGO.length} métodos de pago cargados`);

  for (const u of USOS_CFDI) {
    await prisma.catUsoCfdi.upsert({ where: { clave: u.clave }, update: { descripcion: u.descripcion, personaFisica: u.personaFisica, personaMoral: u.personaMoral }, create: u });
  }
  console.log(`✅ ${USOS_CFDI.length} usos CFDI cargados`);

  for (const m of MONEDAS) {
    await prisma.catMoneda.upsert({ where: { clave: m.clave }, update: { descripcion: m.descripcion, decimales: m.decimales }, create: m });
  }
  console.log(`✅ ${MONEDAS.length} monedas cargadas`);

  for (const cu of CLAVES_UNIDAD) {
    await prisma.catClaveUnidad.upsert({ where: { clave: cu.clave }, update: { descripcion: cu.descripcion }, create: cu });
  }
  console.log(`✅ ${CLAVES_UNIDAD.length} claves de unidad cargadas`);

  for (const oi of OBJETOS_IMP) {
    await prisma.catObjetoImp.upsert({ where: { clave: oi.clave }, update: { descripcion: oi.descripcion }, create: oi });
  }
  console.log(`✅ ${OBJETOS_IMP.length} objetos de impuesto cargados`);

  for (const tr of TIPOS_RELACION) {
    await prisma.catTipoRelacion.upsert({ where: { clave: tr.clave }, update: { descripcion: tr.descripcion }, create: tr });
  }
  console.log(`✅ ${TIPOS_RELACION.length} tipos de relación cargados`);

  for (const ex of EXPORTACIONES) {
    await prisma.catExportacion.upsert({ where: { clave: ex.clave }, update: { descripcion: ex.descripcion }, create: ex });
  }
  console.log(`✅ ${EXPORTACIONES.length} exportaciones cargadas`);

  // Seed precios de planes (editables vía BD — custom no se incluye, se fija por tenant)
  const PLAN_PRICES = [
    { plan: 'starter' as const,      frequency: 'monthly', amount: 199 },
    { plan: 'starter' as const,      frequency: 'annual',  amount: 1990 },
    { plan: 'business' as const,     frequency: 'monthly', amount: 480 },
    { plan: 'business' as const,     frequency: 'annual',  amount: 4800 },
    { plan: 'business_ia' as const,  frequency: 'monthly', amount: 780 },
    { plan: 'business_ia' as const,  frequency: 'annual',  amount: 7800 },
    { plan: 'enterprise' as const,   frequency: 'monthly', amount: 900 },
    { plan: 'enterprise' as const,   frequency: 'annual',  amount: 9000 },
  ];
  for (const p of PLAN_PRICES) {
    await prisma.planPrice.upsert({
      where: { plan_frequency: { plan: p.plan, frequency: p.frequency } },
      update: { amount: p.amount },
      create: p,
    });
  }
  console.log(`✅ ${PLAN_PRICES.length} precios de planes cargados`);

  // Catálogo de paquetes de timbres adicionales. Editables desde panel admin.
  // Se crean con upsert por `cantidad` (unique) — permite reejecutar seed sin
  // sobrescribir precios ya ajustados manualmente: si el row existe, update
  // NO toca el precio (solo active + updatedAt si hace falta), sólo lo crea
  // si no existía. Si se quiere forzar reset de precios, borrar las filas.
  const TIMBRE_PAQUETES = [
    { cantidad: 100,   precio: 200 },
    { cantidad: 1000,  precio: 1400 },
    { cantidad: 10000, precio: 8600 },
  ];
  for (const p of TIMBRE_PAQUETES) {
    await prisma.timbrePaqueteCatalogo.upsert({
      where: { cantidad: p.cantidad },
      update: {}, // No tocamos `precio` si ya existe (admin pudo editarlo)
      create: { cantidad: p.cantidad, precio: p.precio, active: true },
    });
  }
  console.log(`✅ ${TIMBRE_PAQUETES.length} paquetes de timbres en catálogo`);

  const databaseName = 'horux_ede123456ab1';

  // Create demo tenant
  const tenant = await prisma.tenant.upsert({
    where: { rfc: 'EDE123456AB1' },
    update: {},
    create: {
      nombre: 'Empresa Demo SA de CV',
      rfc: 'EDE123456AB1',
      plan: 'business',
      databaseName,
      cfdiLimit: 500,
      usersLimit: 3,
    },
  });

  console.log('✅ Tenant created:', tenant.nombre);

  // Migración: renombra el rol legacy 'admin' a 'owner' si sobrevive de un seed viejo.
  // Idempotente (no-op si ya se renombró o nunca existió).
  await prisma.$executeRawUnsafe(`UPDATE roles SET nombre = 'owner' WHERE nombre = 'admin'`);

  // Backfill de trial_usages para tenants que ya consumieron su trial antes de que
  // existiera esta tabla. Idempotente: ON CONFLICT DO NOTHING.
  await prisma.$executeRawUnsafe(`
    INSERT INTO trial_usages (rfc, tenant_id, started_at)
    SELECT UPPER(rfc), id, COALESCE(created_at, NOW())
    FROM tenants
    WHERE trial_ends_at IS NOT NULL
    ON CONFLICT (rfc) DO NOTHING
  `);

  // Backfill de user_platform_roles: los owners del tenant HTS240708LJA se
  // convierten automáticamente en platform_admin. Esto preserva el comportamiento
  // anterior (admin global por RFC) al mismo tiempo que abre la puerta al modelo
  // de roles granulares. Idempotente.
  await prisma.$executeRawUnsafe(`
    INSERT INTO user_platform_roles (user_id, role, created_at)
    SELECT u.id, 'platform_admin'::"PlatformRole", NOW()
    FROM users u
    JOIN tenants t ON u.tenant_id = t.id
    JOIN roles r ON u.rol_id = r.id
    WHERE t.rfc = 'HTS240708LJA' AND r.nombre = 'owner'
    ON CONFLICT (user_id, role) DO NOTHING
  `);

  // Backfill de tenant_memberships: cada user existente genera una membership
  // con su tenant y rol actuales. isOwner = true si su rol es 'owner' (u 'cfo',
  // que es equivalente en permisos). Esto es el fundamento del modelo multi-tenant
  // — durante la transición, User.tenantId sigue siendo el "default tenant" para
  // login UX, pero las autorizaciones verdaderas vienen de esta tabla.
  // Idempotente: ON CONFLICT evita duplicados al re-correr seed.
  await prisma.$executeRawUnsafe(`
    INSERT INTO tenant_memberships (user_id, tenant_id, rol_id, is_owner, active, joined_at)
    SELECT u.id, u.tenant_id, u.rol_id, (r.nombre IN ('owner', 'cfo')), u.active, u.created_at
    FROM users u
    JOIN roles r ON u.rol_id = r.id
    ON CONFLICT (user_id, tenant_id) DO NOTHING
  `);

  // Seed roles
  const rolesData = [
    { nombre: 'owner', descripcion: 'Dueño - acceso completo' },
    { nombre: 'cfo', descripcion: 'CFO - acceso completo (mismo nivel que el dueño)' },
    { nombre: 'contador', descripcion: 'Contador - dashboard, CFDI, impuestos, calendario, alertas, facturación' },
    { nombre: 'auxiliar', descripcion: 'Auxiliar - mismos permisos que contador' },
    { nombre: 'visor', descripcion: 'Visor - solo lectura de CFDI, impuestos, calendario, alertas' },
  ];
  for (const r of rolesData) {
    await prisma.rol.upsert({
      where: { nombre: r.nombre },
      update: { descripcion: r.descripcion },
      create: r,
    });
  }

  // Seed despacho roles
  await prisma.rol.upsert({
    where: { nombre: 'supervisor' },
    update: {},
    create: { id: 9, nombre: 'supervisor', descripcion: 'Supervisor de despacho — titular de RFCs, crea carteras' },
  });

  await prisma.rol.upsert({
    where: { nombre: 'cliente' },
    update: {},
    create: { id: 10, nombre: 'cliente', descripcion: 'Cliente visor externo — acceso read-only a sus RFCs' },
  });

  const roles = await prisma.rol.findMany();
  const rolMap = new Map(roles.map(r => [r.nombre, r.id]));
  console.log(`✅ ${roles.length} roles cargados`);

  // Create demo users
  const passwordHash = await bcrypt.hash('demo123', 12);

  const users = [
    { email: 'admin@demo.com', nombre: 'Dueño Demo', rolNombre: 'owner' },
    { email: 'contador@demo.com', nombre: 'Contador Demo', rolNombre: 'contador' },
    { email: 'visor@demo.com', nombre: 'Visor Demo', rolNombre: 'visor' },
  ];

  for (const userData of users) {
    const user = await prisma.user.upsert({
      where: { email: userData.email },
      update: {},
      create: {
        tenantId: tenant.id,
        email: userData.email,
        passwordHash,
        nombre: userData.nombre,
        rolId: rolMap.get(userData.rolNombre)!,
      },
      include: { rol: true },
    });
    console.log(`✅ User created: ${user.email} (${user.rol.nombre})`);
  }

  // Create tenant database
  const dbConfig = parseDatabaseUrl(process.env.DATABASE_URL!);
  const adminPool = new Pool({ ...dbConfig, database: 'postgres', max: 1 });

  try {
    const exists = await adminPool.query(
      `SELECT 1 FROM pg_database WHERE datname = $1`,
      [databaseName]
    );

    if (exists.rows.length === 0) {
      await adminPool.query(`CREATE DATABASE "${databaseName}"`);
      console.log(`✅ Tenant database created: ${databaseName}`);
    } else {
      console.log(`ℹ️  Tenant database already exists: ${databaseName}`);
    }
  } finally {
    await adminPool.end();
  }

  // Create tables in tenant database
  const tenantPool = new Pool({ ...dbConfig, database: databaseName, max: 1 });

  try {
    // Reset tenant tables so the re-seed parte de cero. Luego corremos las
    // migraciones (fuente única de verdad del schema tenant) para garantizar
    // que queden todas las tablas y columnas actuales.
    await tenantPool.query(`
      DROP TABLE IF EXISTS cfdi_conceptos CASCADE;
      DROP TABLE IF EXISTS cfdis CASCADE;
      DROP TABLE IF EXISTS conciliaciones CASCADE;
      DROP TABLE IF EXISTS bancos CASCADE;
      DROP TABLE IF EXISTS recordatorios CASCADE;
      DROP TABLE IF EXISTS alertas CASCADE;
      DROP TABLE IF EXISTS rfcs CASCADE;
      DROP TABLE IF EXISTS opiniones_cumplimiento CASCADE;
      DROP TABLE IF EXISTS schema_migrations;
    `);

    await migrate(tenantPool, tenant.rfc);
    console.log('✅ Tenant schema aplicado vía migraciones');

    // Bloque legacy de CREATE TABLE / CREATE INDEX retirado: vive ahora en
    // `apps/api/src/migrations/tenant/*.sql` (fuente única de verdad).

    // Insert demo CFDIs with new structure
    const cfdiTypes = ['EMITIDO', 'RECIBIDO'];
    const tipoComprobantes: Record<string, string> = { EMITIDO: 'I', RECIBIDO: 'I' };
    const rfcs = ['XAXX010101000', 'MEXX020202000', 'AAXX030303000', 'BBXX040404000'];
    const nombres = ['Cliente Demo SA', 'Proveedor ABC', 'Servicios XYZ', 'Materiales 123'];

    for (let i = 0; i < 50; i++) {
      const tipo = cfdiTypes[i % 2];
      const rfcIndex = i % 4;
      const subtotal = Math.floor(Math.random() * 50000) + 1000;
      const iva = subtotal * 0.16;
      const total = subtotal + iva;
      const daysAgo = Math.floor(Math.random() * 180);
      const fecha = new Date();
      fecha.setDate(fecha.getDate() - daysAgo);
      const year = String(fecha.getFullYear());
      const month = String(fecha.getMonth() + 1).padStart(2, '0');

      await tenantPool.query(`
        INSERT INTO cfdis (
          year, month, type, uuid, serie, folio, status, fecha_emision,
          rfc_emisor, nombre_emisor, rfc_receptor, nombre_receptor,
          subtotal, subtotal_mxn, descuento, descuento_mxn,
          total, total_mxn, moneda, tipo_cambio, tipo_comprobante,
          metodo_pago, iva_traslado, iva_traslado_mxn,
          regimen_fiscal_emisor, regimen_fiscal_receptor
        ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26)
        ON CONFLICT (uuid) DO NOTHING
      `, [
        year, month, tipo, crypto.randomUUID(), 'A', String(1000 + i),
        'Vigente', fecha,
        tipo === 'EMITIDO' ? 'EDE123456AB1' : rfcs[rfcIndex],
        tipo === 'EMITIDO' ? 'Empresa Demo SA de CV' : nombres[rfcIndex],
        tipo === 'RECIBIDO' ? 'EDE123456AB1' : rfcs[rfcIndex],
        tipo === 'RECIBIDO' ? 'Empresa Demo SA de CV' : nombres[rfcIndex],
        subtotal, subtotal, 0, 0,
        total, total, 'MXN', 1, tipoComprobantes[tipo],
        'PUE', iva, iva,
        '601', '601',
      ]);
    }

    console.log('✅ Demo CFDIs created (50)');

    // Insert demo conceptos for each CFDI
    const { rows: allCfdis } = await tenantPool.query(`SELECT id FROM cfdis`);
    const productos = ['Servicio de consultoría', 'Licencia de software', 'Soporte técnico', 'Desarrollo web', 'Capacitación'];

    for (const c of allCfdis) {
      const numConceptos = Math.floor(Math.random() * 3) + 1;
      for (let j = 0; j < numConceptos; j++) {
        const cantidad = Math.floor(Math.random() * 5) + 1;
        const valorUnitario = Math.floor(Math.random() * 5000) + 500;
        const importe = cantidad * valorUnitario;
        const iva = importe * 0.16;

        await tenantPool.query(`
          INSERT INTO cfdi_conceptos (
            cfdi_id, clave_prod_serv, descripcion, cantidad, clave_unidad, unidad,
            valor_unitario, valor_unitario_mxn,
            importe, importe_mxn, descuento, descuento_mxn,
            iva_traslado, iva_traslado_mxn
          ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14)
        `, [
          c.id,
          '84111506', productos[j % productos.length], cantidad, 'E48', 'Servicio',
          valorUnitario, valorUnitario,
          importe, importe, 0, 0,
          iva, iva,
        ]);
      }
    }

    console.log('✅ Demo conceptos created');

  } finally {
    await tenantPool.end();
  }

  // Seed plan catalog for CONTABLE vertical
  const planCatalogoData = [
    {
      codename: 'trial_contable',
      nombre: 'Trial Contable',
      verticalProfile: 'CONTABLE' as const,
      precioBase: 0,
      frecuencia: 'mensual',
      limits: { maxRfcs: 3, maxUsers: 1, timbresIncluidosMes: 20, features: ['dashboard', 'cfdi_basic', 'iva_isr'] },
    },
    {
      codename: 'starter_contable',
      nombre: 'Starter Contable',
      verticalProfile: 'CONTABLE' as const,
      precioBase: 490,
      frecuencia: 'mensual',
      limits: { maxRfcs: 10, maxUsers: 3, timbresIncluidosMes: 50, features: ['dashboard', 'cfdi_basic', 'iva_isr', 'alertas', 'calendario'] },
    },
    {
      codename: 'business_contable',
      nombre: 'Business Contable',
      verticalProfile: 'CONTABLE' as const,
      precioBase: 1290,
      frecuencia: 'mensual',
      limits: { maxRfcs: 50, maxUsers: 10, timbresIncluidosMes: 200, features: ['dashboard', 'cfdi_basic', 'iva_isr', 'alertas', 'calendario', 'reportes', 'conciliacion', 'documentos', 'facturacion'] },
    },
    {
      codename: 'enterprise_contable',
      nombre: 'Enterprise Contable',
      verticalProfile: 'CONTABLE' as const,
      precioBase: 2990,
      frecuencia: 'mensual',
      limits: { maxRfcs: -1, maxUsers: -1, timbresIncluidosMes: 600, features: ['dashboard', 'cfdi_basic', 'iva_isr', 'alertas', 'calendario', 'reportes', 'conciliacion', 'documentos', 'facturacion', 'api'] },
    },
  ];

  for (const p of planCatalogoData) {
    await prisma.planCatalogo.upsert({
      where: { codename: p.codename },
      update: { nombre: p.nombre, precioBase: p.precioBase, limits: p.limits },
      create: p,
    });
  }
  console.log('✓ Plan catalog seeded (4 plans CONTABLE)');

  // Seed addon catalog
  const addonCatalogoData = [
    {
      codename: 'rfcs_extra_10',
      nombre: '+10 RFCs adicionales',
      verticalProfile: 'CONTABLE' as const,
      precio: 190,
      frecuencia: 'mensual',
      delta: { maxRfcs: 10 },
    },
    {
      codename: 'rfcs_extra_50',
      nombre: '+50 RFCs adicionales',
      verticalProfile: 'CONTABLE' as const,
      precio: 690,
      frecuencia: 'mensual',
      delta: { maxRfcs: 50 },
    },
    {
      codename: 'timbres_extra_500',
      nombre: '+500 timbres mensuales',
      precio: 490,
      frecuencia: 'mensual',
      delta: { timbresIncluidosMes: 500 },
    },
    {
      codename: 'modulo_ia',
      nombre: 'Módulo IA Fiscal',
      precio: 390,
      frecuencia: 'mensual',
      delta: { features: ['ia_lolita'] },
    },
    {
      // Lolita IA activable por contribuyente específico del despacho.
      // SubscriptionAddon.contribuyenteId apunta al RFC que lo contrata.
      // Cobro mensual en preapproval propio (la licencia del despacho es anual;
      // el add-on va en ciclo independiente).
      codename: 'lolita_ia_contribuyente',
      nombre: 'Lolita IA (por contribuyente)',
      verticalProfile: 'CONTABLE' as const,
      precio: 250,
      frecuencia: 'mensual',
      delta: { features: ['ia_lolita'] },
    },
    {
      // Contribuyente adicional para planes Business Control y Enterprise
      // (ambos incluyen 100 base). Se cobra automáticamente según overage; no
      // requiere opt-in, pero se modela como add-on para que el preapproval MP
      // lo cubra. El codename mantiene el sufijo "business_cloud" por compat
      // con suscripciones existentes; el nombre display ya es genérico.
      codename: 'contribuyente_extra_business_cloud',
      nombre: 'Contribuyente adicional (RFC extra)',
      verticalProfile: 'CONTABLE' as const,
      precio: 45,
      frecuencia: 'mensual',
      delta: { maxRfcs: 1 },
    },
  ];

  for (const a of addonCatalogoData) {
    await prisma.planAddonCatalogo.upsert({
      where: { codename: a.codename },
      update: { nombre: a.nombre, precio: a.precio, delta: a.delta },
      create: { ...a, verticalProfile: a.verticalProfile ?? null },
    });
  }
  console.log('✓ Addon catalog seeded (6 addons)');

  console.log('\n🎉 Seed completed successfully!');
  console.log('\n📝 Demo credentials:');
  console.log('   Admin:    admin@demo.com / demo123');
  console.log('   Contador: contador@demo.com / demo123');
  console.log('   Visor:    visor@demo.com / demo123');
}

main()
  .catch((e) => {
    console.error('Error seeding database:', e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
