import 'dotenv/config';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
import { eq, sql } from 'drizzle-orm';
import { computeBudget } from '../budget';
import type { BudgetInputs } from '../budget/types';
import { hashPassword } from '../lib/auth/password';

const connectionString = process.env.DATABASE_URL;
if (!connectionString) {
  throw new Error('DATABASE_URL no está definida.');
}

const client = postgres(connectionString, { prepare: false });
const db = drizzle(client, { schema });

const euros = (n: number) => Math.round(n * 100); // a céntimos

// Factor de zona geográfica por provincia/ciudad. Las no listadas valen 1.0 (media nacional).
// Tramos: Madrid/Barcelona 1.40, islas 1.30, capitales grandes 1.20, rural/interior 0.85.
const ZONA_FACTORES: Record<string, number> = Object.fromEntries(
  [
    [['Madrid', 'Barcelona'], 1.4],
    [
      ['Baleares', 'Islas Baleares', 'Palma', 'Mallorca', 'Las Palmas', 'Tenerife', 'Santa Cruz de Tenerife', 'Canarias'],
      1.3,
    ],
    [
      ['Valencia', 'Sevilla', 'Málaga', 'Bilbao', 'Vizcaya', 'Bizkaia', 'Zaragoza', 'Alicante', 'Murcia', 'San Sebastián', 'Gipuzkoa', 'Vitoria', 'Granada', 'Valladolid'],
      1.2,
    ],
    [
      ['Cuenca', 'Teruel', 'Soria', 'Zamora', 'Ávila', 'Palencia', 'Ourense', 'Lugo', 'Cáceres', 'Badajoz', 'Ciudad Real', 'Albacete', 'Jaén', 'Huesca', 'Segovia', 'Guadalajara'],
      0.85,
    ],
  ].flatMap(([nombres, factor]) => (nombres as string[]).map((n) => [n, factor as number])),
);

// Cada lead vive en un momento distinto del funnel para poder analizar
// cuál es el siguiente paso de cada uno. days = hace cuántos días entró.
type SeedLead = {
  nombre: string;
  telefono: string;
  email: string;
  provincia: string;
  tipoReforma: (typeof schema.tipoReforma.enumValues)[number];
  pipelineStage: (typeof schema.pipelineStage.enumValues)[number];
  estado: (typeof schema.leadEstado.enumValues)[number];
  presupuestoEstimado: number | null;
  transcripcion: string | null;
  entidades: Record<string, unknown> | null;
  renderUrl: string | null;
  pdfUrl: string | null;
  audioUrl: string | null;
  fotos: string[];
  daysAgo: number;
  precioFinal?: number; // solo para ganados
};

const SEED_LEADS: SeedLead[] = [
  {
    // 1. Acaba de dejar sus datos. Siguiente paso: subir fotos.
    nombre: 'Lucía Fernández',
    telefono: '+34 612 003 451',
    email: 'lucia.fernandez@example.com',
    provincia: 'Madrid',
    tipoReforma: 'cocina',
    pipelineStage: 'form_completado',
    estado: 'nuevo',
    presupuestoEstimado: null,
    transcripcion: null,
    entidades: null,
    renderUrl: null,
    pdfUrl: null,
    audioUrl: null,
    fotos: [],
    daysAgo: 0,
  },
  {
    // 2. Subió fotos. Siguiente paso: pre-llamada SMS+WhatsApp.
    nombre: 'Javier Ortega',
    telefono: '+34 633 118 902',
    email: 'javier.ortega@example.com',
    provincia: 'Valencia',
    tipoReforma: 'bano',
    pipelineStage: 'fotos_subidas',
    estado: 'nuevo',
    presupuestoEstimado: null,
    transcripcion: null,
    entidades: null,
    renderUrl: null,
    pdfUrl: null,
    audioUrl: null,
    fotos: ['/antes-bano.webp'],
    daysAgo: 0,
  },
  {
    // 3. Pre-llamada enviada, pendiente de descolgar. Siguiente: llamada agente.
    nombre: 'Marta Ruiz',
    telefono: '+34 655 740 213',
    email: 'marta.ruiz@example.com',
    provincia: 'Sevilla',
    tipoReforma: 'comedor',
    pipelineStage: 'prellamada_enviada',
    estado: 'nuevo',
    presupuestoEstimado: null,
    transcripcion: null,
    entidades: null,
    renderUrl: null,
    pdfUrl: null,
    audioUrl: null,
    fotos: ['/antes-comedor.webp'],
    daysAgo: 1,
  },
  {
    // 4. Llamada completada. Siguiente: render IA.
    nombre: 'Andrés Gil',
    telefono: '+34 677 552 008',
    email: 'andres.gil@example.com',
    provincia: 'Málaga',
    tipoReforma: 'cocina',
    pipelineStage: 'llamada_completada',
    estado: 'nuevo',
    presupuestoEstimado: null,
    transcripcion:
      'Agente: Hola Andrés, te llamo de Reformas Ejemplo. Te aviso de que soy un asistente con IA y de que la llamada se graba. ¿Quieres reformar la cocina entera? Andrés: Sí, son unos 12 metros, quiero quitar un tabique...',
    entidades: {
      espacio: 'cocina',
      m2_aprox: 12,
      tirar_tabique: true,
      calidad: 'media',
      licencia_urbanistica: 'posible',
    },
    renderUrl: null,
    pdfUrl: null,
    audioUrl: '/demo/audio-andres.mp3',
    fotos: ['/antes.webp'],
    daysAgo: 1,
  },
  {
    // 5. Render generado, falta presupuesto+PDF. Siguiente: motor presupuesto.
    nombre: 'Patricia Núñez',
    telefono: '+34 688 410 776',
    email: 'patricia.nunez@example.com',
    provincia: 'Zaragoza',
    tipoReforma: 'bano',
    pipelineStage: 'render_generado',
    estado: 'nuevo',
    presupuestoEstimado: null,
    transcripcion:
      'Agente: Hola Patricia... Patricia: Quiero cambiar la bañera por un plato de ducha y alicatar todo.',
    entidades: {
      espacio: 'bano',
      m2_aprox: 6,
      banera_por_ducha: true,
      alicatado_completo: true,
      calidad: 'media',
    },
    renderUrl: '/despues-bano.webp',
    pdfUrl: null,
    audioUrl: '/demo/audio-patricia.mp3',
    fotos: ['/antes-bano.webp'],
    daysAgo: 2,
  },
  {
    // 6. Presupuesto + PDF listos, sin entregar aún. Siguiente: WhatsApp.
    nombre: 'Roberto Salas',
    telefono: '+34 699 320 145',
    email: 'roberto.salas@example.com',
    provincia: 'Barcelona',
    tipoReforma: 'integral',
    pipelineStage: 'presupuesto_generado',
    estado: 'nuevo',
    presupuestoEstimado: euros(28400),
    transcripcion:
      'Agente: Hola Roberto... Roberto: Es un piso de 70 metros, lo quiero reformar entero, suelo, baño, cocina y pintura.',
    entidades: {
      espacio: 'integral',
      m2_aprox: 70,
      incluye: ['suelo', 'bano', 'cocina', 'pintura'],
      calidad: 'media',
    },
    renderUrl: '/despues.webp',
    pdfUrl: '/demo/presupuesto-roberto.pdf',
    audioUrl: '/demo/audio-roberto.mp3',
    fotos: ['/antes.webp', '/antes-comedor.webp'],
    daysAgo: 2,
  },
  {
    // 7. Entregado al cliente por WhatsApp. Lead caliente recién llegado al panel.
    nombre: 'Elena Castro',
    telefono: '+34 600 781 459',
    email: 'elena.castro@example.com',
    provincia: 'Madrid',
    tipoReforma: 'cocina',
    pipelineStage: 'whatsapp_entregado',
    estado: 'nuevo',
    presupuestoEstimado: euros(15600),
    transcripcion:
      'Agente: Hola Elena... Elena: Quiero renovar la cocina, muebles nuevos y encimera de cuarzo.',
    entidades: {
      espacio: 'cocina',
      m2_aprox: 10,
      muebles_nuevos: true,
      encimera: 'cuarzo',
      calidad: 'media-alta',
    },
    renderUrl: '/despues.webp',
    pdfUrl: '/demo/presupuesto-elena.pdf',
    audioUrl: '/demo/audio-elena.mp3',
    fotos: ['/antes.webp'],
    daysAgo: 3,
  },
  {
    // Entregado y ya contactado por el reformista. Siguiente: agendar visita.
    nombre: 'Tomás Herrero',
    telefono: '+34 611 902 334',
    email: 'tomas.herrero@example.com',
    provincia: 'Bilbao',
    tipoReforma: 'bano',
    pipelineStage: 'whatsapp_entregado',
    estado: 'contactado',
    presupuestoEstimado: euros(9800),
    transcripcion: 'Agente: Hola Tomás... Tomás: Solo el baño, cambiar todo el alicatado y sanitarios.',
    entidades: { espacio: 'bano', m2_aprox: 5, sanitarios_nuevos: true, calidad: 'media' },
    renderUrl: '/despues-bano.webp',
    pdfUrl: '/demo/presupuesto-tomas.pdf',
    audioUrl: '/demo/audio-tomas.mp3',
    fotos: ['/antes-bano.webp'],
    daysAgo: 5,
  },
  {
    // Visita agendada. Siguiente: hacer la visita y enviar presupuesto firmado.
    nombre: 'Carmen Ibáñez',
    telefono: '+34 622 145 870',
    email: 'carmen.ibanez@example.com',
    provincia: 'Madrid',
    tipoReforma: 'comedor',
    pipelineStage: 'whatsapp_entregado',
    estado: 'visita_agendada',
    presupuestoEstimado: euros(7200),
    transcripcion: 'Agente: Hola Carmen... Carmen: Quiero abrir el comedor al salón y poner tarima.',
    entidades: { espacio: 'comedor', m2_aprox: 20, tarima: true, calidad: 'media' },
    renderUrl: '/despues-comedor.webp',
    pdfUrl: '/demo/presupuesto-carmen.pdf',
    audioUrl: '/demo/audio-carmen.mp3',
    fotos: ['/antes-comedor.webp'],
    daysAgo: 8,
  },
  {
    // Ganado: precio final firmado, alimenta precision_history. RF-D-04.
    nombre: 'Diego Romero',
    telefono: '+34 633 770 218',
    email: 'diego.romero@example.com',
    provincia: 'Valencia',
    tipoReforma: 'integral',
    pipelineStage: 'whatsapp_entregado',
    estado: 'ganado',
    presupuestoEstimado: euros(31000),
    transcripcion: 'Agente: Hola Diego... Diego: Reforma integral de un piso de 85 metros heredado.',
    entidades: { espacio: 'integral', m2_aprox: 85, calidad: 'alta' },
    renderUrl: '/despues.webp',
    pdfUrl: '/demo/presupuesto-diego.pdf',
    audioUrl: '/demo/audio-diego.mp3',
    fotos: ['/antes.webp'],
    daysAgo: 25,
    precioFinal: euros(33500),
  },
  {
    // Perdido: el cliente no siguió adelante.
    nombre: 'Sara Blanco',
    telefono: '+34 644 318 092',
    email: 'sara.blanco@example.com',
    provincia: 'Sevilla',
    tipoReforma: 'cocina',
    pipelineStage: 'whatsapp_entregado',
    estado: 'perdido',
    presupuestoEstimado: euros(14200),
    transcripcion: 'Agente: Hola Sara... Sara: Quería una idea de precio para la cocina.',
    entidades: { espacio: 'cocina', m2_aprox: 9, calidad: 'media' },
    renderUrl: '/despues.webp',
    pdfUrl: '/demo/presupuesto-sara.pdf',
    audioUrl: '/demo/audio-sara.mp3',
    fotos: ['/antes.webp'],
    daysAgo: 18,
  },
];

// Orden cronológico del funnel para reconstruir el timeline de cada lead.
const STAGE_ORDER = schema.pipelineStage.enumValues;

async function main() {
  const [existing] = await db
    .select()
    .from(schema.tenants)
    .where(eq(schema.tenants.slug, 'reformas-ejemplo'))
    .limit(1);
  if (existing && !process.env.SEED_FORCE) {
    console.log('Ya hay datos (tenant "reformas-ejemplo"). Saltando seed. Usa SEED_FORCE=1 para forzar.');
    await client.end();
    return;
  }

  console.log('Limpiando datos previos...');
  await db.execute(
    sql`TRUNCATE TABLE ${schema.testimonioFotos}, ${schema.testimonios}, ${schema.precisionHistory}, ${schema.leadPipelineEventos}, ${schema.leadEstadoHistory}, ${schema.leadFotos}, ${schema.leads}, ${schema.sessions}, ${schema.users}, ${schema.plans}, ${schema.tenants} RESTART IDENTITY CASCADE`
  );

  console.log('Sembrando planes...');
  const [, pro] = await db
    .insert(schema.plans)
    .values([
      {
        slug: 'starter',
        nombre: 'Starter',
        precioMensual: 2900,
        leadsIncluidos: 5,
        features: ['5 leads procesados / mes', '3 €/lead extra', 'Hasta 100 contactos', 'Branding básico'],
      },
      {
        slug: 'pro',
        nombre: 'Pro',
        precioMensual: 7900,
        leadsIncluidos: 15,
        features: [
          '15 leads procesados / mes',
          '2,50 €/lead extra',
          'White-label completo',
          'Sub-flujo licencia urbanística',
          'Integraciones Holded/Stel',
          'Soporte prioritario',
        ],
      },
      {
        slug: 'business',
        nombre: 'Business',
        precioMensual: 19900,
        leadsIncluidos: 50,
        features: [
          '50 leads procesados / mes',
          '2 €/lead extra',
          'Usuarios ilimitados',
          'API',
          'Multi-zona',
          'Custom price book',
          'Dashboard analytics',
        ],
      },
    ])
    .returning();

  console.log('Creando tenant "Reformas Ejemplo"...');
  const [tenant] = await db
    .insert(schema.tenants)
    .values({
      slug: 'reformas-ejemplo',
      nombreEmpresa: 'Reformas Ejemplo',
      provincia: 'Madrid',
      whatsappBusiness: '+34 600 000 000',
      planId: pro.id,
      subscriptionStatus: 'trial',
      trialEndsAt: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000),
      seoTitle: 'Reformas Ejemplo · Reformas integrales en Madrid',
      seoDescription:
        'Pide tu presupuesto de reforma con render IA en minutos. Reformas de cocina, baño y vivienda completa en Madrid.',
      aboutEnabled: true,
      aboutTexto:
        'Somos un equipo de Madrid especializado en reformas integrales de cocinas, baños y viviendas completas. Cuidamos cada detalle y te acompañamos desde la primera idea hasta la entrega de llaves, con presupuestos claros y sin sorpresas.',
      aniosExperiencia: 15,
    })
    .returning();

  console.log('Creando usuarios demo (admin + owner)...');
  await db.insert(schema.users).values([
    {
      email: 'admin@reformix.es',
      passwordHash: await hashPassword('AdminReformix2026!'),
      nombre: 'Admin Reformix',
      role: 'admin',
      tenantId: null,
    },
    {
      email: 'demo@reformas-ejemplo.es',
      passwordHash: await hashPassword('DemoReformix2026!'),
      nombre: 'Reformas Ejemplo',
      role: 'reformista',
      tenantId: tenant.id,
    },
  ]);

  console.log(`Insertando ${SEED_LEADS.length} leads...`);
  for (const l of SEED_LEADS) {
    const createdAt = new Date(Date.now() - l.daysAgo * 24 * 60 * 60 * 1000);

    const [lead] = await db
      .insert(schema.leads)
      .values({
        tenantId: tenant.id,
        createdAt,
        updatedAt: createdAt,
        nombre: l.nombre,
        telefono: l.telefono,
        email: l.email,
        provincia: l.provincia,
        tipoReforma: l.tipoReforma,
        consentPrivacidad: true,
        consentContratacion: true,
        pipelineStage: l.pipelineStage,
        estado: l.estado,
        presupuestoEstimado: l.presupuestoEstimado,
        transcripcion: l.transcripcion,
        entidades: l.entidades,
        renderUrl: l.renderUrl,
        pdfUrl: l.pdfUrl,
        audioUrl: l.audioUrl,
      })
      .returning();

    // Fotos
    if (l.fotos.length) {
      await db.insert(schema.leadFotos).values(
        l.fotos.map((url, orden) => ({ leadId: lead.id, url, orden }))
      );
    }

    // Timeline del funnel: un evento por cada paso alcanzado hasta el actual.
    const reached = STAGE_ORDER.slice(0, STAGE_ORDER.indexOf(l.pipelineStage) + 1);
    await db.insert(schema.leadPipelineEventos).values(
      reached.map((stage, i) => ({
        leadId: lead.id,
        stage,
        occurredAt: new Date(createdAt.getTime() + i * 5 * 60 * 1000),
      }))
    );

    // Histórico de estado (siempre nace en 'nuevo')
    const estados: (typeof schema.leadEstado.enumValues)[number][] =
      l.estado === 'nuevo' ? ['nuevo'] : ['nuevo', l.estado];
    await db.insert(schema.leadEstadoHistory).values(
      estados.map((estado, i) => ({
        leadId: lead.id,
        estado,
        changedAt: new Date(createdAt.getTime() + i * 60 * 60 * 1000),
      }))
    );

    // Precisión para ganados (RF-D-04)
    if (l.estado === 'ganado' && l.precioFinal && l.presupuestoEstimado) {
      const deltaPct = ((l.precioFinal - l.presupuestoEstimado) / l.presupuestoEstimado) * 100;
      await db.insert(schema.precisionHistory).values({
        leadId: lead.id,
        estimated: l.presupuestoEstimado,
        final: l.precioFinal,
        deltaPct: deltaPct.toFixed(2),
      });
    }
  }

  // --- Opiniones demo (recogidas en el funnel de review, ya moderadas) ---
  console.log('Sembrando opiniones demo...');
  const leadsPorEmail = await db
    .select({ id: schema.leads.id, email: schema.leads.email })
    .from(schema.leads)
    .where(eq(schema.leads.tenantId, tenant.id));
  const leadIdPorEmail = new Map(leadsPorEmail.map((l) => [l.email, l.id]));

  // Diego (ganado) ya tiene la opinión solicitada desde el panel.
  const diegoId = leadIdPorEmail.get('diego.romero@example.com');
  if (diegoId) {
    await db
      .update(schema.leads)
      .set({ testimonioSolicitadoAt: new Date(Date.now() - 20 * 24 * 60 * 60 * 1000) })
      .where(eq(schema.leads.id, diegoId));
  }

  const [testiDiego] = await db
    .insert(schema.testimonios)
    .values({
      tenantId: tenant.id,
      leadId: diegoId ?? null,
      nombre: 'Diego Romero',
      contexto: 'Reforma integral · Valencia',
      rating: 5,
      texto:
        'Reformaron un piso heredado de 85 metros de arriba a abajo. El presupuesto inicial cuadró casi al detalle con el final y los plazos se cumplieron. Repetiría sin dudarlo.',
      estado: 'publicado',
    })
    .returning();
  if (testiDiego) {
    await db
      .insert(schema.testimonioFotos)
      .values({ testimonioId: testiDiego.id, url: '/despues.webp', orden: 0 });
  }

  await db.insert(schema.testimonios).values([
    {
      tenantId: tenant.id,
      leadId: leadIdPorEmail.get('carmen.ibanez@example.com') ?? null,
      nombre: 'Carmen Ibáñez',
      contexto: 'Comedor · Madrid',
      rating: 5,
      texto:
        'Abrieron el comedor al salón y pusieron tarima nueva. El render que me enseñaron al principio era casi idéntico al resultado final. Trato impecable.',
      estado: 'publicado',
    },
    {
      // Pendiente de aprobar: aparece en el panel pero aún no en la landing.
      tenantId: tenant.id,
      leadId: leadIdPorEmail.get('tomas.herrero@example.com') ?? null,
      nombre: 'Tomás Herrero',
      contexto: 'Baño · Bilbao',
      rating: 4,
      texto:
        'Cambiaron todo el alicatado y los sanitarios del baño. Buen acabado y limpios. Solo se retrasaron un par de días por los materiales.',
      estado: 'pendiente',
    },
  ]);

  // --- Precios + catálogo demo (motor de presupuesto) ---
  const [tenantRow] = await db
    .select()
    .from(schema.tenants)
    .where(eq(schema.tenants.slug, 'reformas-ejemplo'))
    .limit(1);

  if (tenantRow) {
    await db.delete(schema.catalogItems).where(eq(schema.catalogItems.tenantId, tenantRow.id));
    await db.delete(schema.pricingConfig).where(eq(schema.pricingConfig.tenantId, tenantRow.id));

    const [config] = await db
      .insert(schema.pricingConfig)
      .values({
        tenantId: tenantRow.id,
        alturaTechoDefault: 2.5,
        factorZona: ZONA_FACTORES,
        manoObra: {
          demolicion: 5000,
          impermeabilizacion: 4500,
          fontaneria: 14600,
          electricidad: 5400,
          mano_de_obra: 7500,
        },
        extras: { tuberias: 115000, boletin: 17500, distribucion: 90000 },
      })
      .returning();

    const cat = (
      categoria: 'suelo' | 'pared' | 'pintura' | 'mobiliario',
      nombre: string,
      calidad: 'basica' | 'media' | 'premium',
      precioEuros: number,
      unidad: 'm2' | 'ml' | 'ud',
      descriptorRender: string,
      sku: string,
    ) => ({
      tenantId: tenantRow.id,
      categoria,
      nombre,
      calidad,
      precioUnit: Math.round(precioEuros * 100),
      unidad,
      descriptorRender,
      esDefault: true,
      sku,
    });

    const catalog = await db.insert(schema.catalogItems).values([
      cat('suelo', 'Gres cerámico básico', 'basica', 40, 'm2', 'suelo gres beige liso', 'SUE-B'),
      cat('suelo', 'Porcelánico símil madera', 'media', 70, 'm2', 'porcelánico símil roble claro', 'SUE-M'),
      cat('suelo', 'Porcelánico gran formato', 'premium', 170, 'm2', 'porcelánico gran formato gris piedra', 'SUE-P'),
      cat('pared', 'Azulejo blanco brillo', 'basica', 32, 'm2', 'azulejo blanco brillo 20x20', 'PAR-B'),
      cat('pared', 'Azulejo rectificado', 'media', 60, 'm2', 'azulejo rectificado blanco mate 30x60', 'PAR-M'),
      cat('pared', 'Porcelánico decorativo', 'premium', 140, 'm2', 'porcelánico decorativo símil mármol', 'PAR-P'),
      cat('pintura', 'Plástica mate', 'basica', 6, 'm2', 'pintura plástica blanca mate', 'PIN-B'),
      cat('pintura', 'Plástica lavable', 'media', 9, 'm2', 'pintura lavable blanco roto', 'PIN-M'),
      cat('pintura', 'Esmalte premium', 'premium', 14, 'm2', 'esmalte al agua acabado seda gris perla', 'PIN-P'),
      cat('mobiliario', 'Muebles melamina', 'basica', 180, 'ml', 'muebles cocina melamina blanca', 'MOB-B'),
      cat('mobiliario', 'Muebles laminado', 'media', 320, 'ml', 'muebles cocina laminado roble con tirador integrado', 'MOB-M'),
      cat('mobiliario', 'Muebles lacado', 'premium', 550, 'ml', 'muebles cocina lacado mate antracita y encimera porcelánica', 'MOB-P'),
    ]).returning();

    // Inputs demo en un lead ya avanzado + presupuesto ya calculado para que el
    // desglose sea visible al abrir el detalle (Roberto: integral 70 m², Barcelona).
    const [roberto] = await db
      .update(schema.leads)
      .set({ m2Suelo: 70, calidadGlobal: 'media', estructural: false })
      .where(eq(schema.leads.email, 'roberto.salas@example.com'))
      .returning();

    if (roberto) {
      const inputs: BudgetInputs = {
        tipoReforma: roberto.tipoReforma ?? 'integral',
        m2Suelo: roberto.m2Suelo,
        alturaTecho: roberto.alturaTecho ?? null,
        calidadGlobal: roberto.calidadGlobal ?? 'media',
        estructural: roberto.estructural,
        provincia: roberto.provincia ?? null,
        materialSelections: {},
      };
      const result = computeBudget(inputs, config, catalog);
      await db
        .update(schema.leads)
        .set({
          presupuestoEstimado: result.total,
          desgloseSnapshot: { stage: roberto.pipelineStage, result },
        })
        .where(eq(schema.leads.id, roberto.id));
    }
  }

  console.log('Seed completado.');
  await client.end();
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
