'use server';

import { z } from 'zod';
import { and, eq } from 'drizzle-orm';
import { redirect } from 'next/navigation';
import { revalidatePath } from 'next/cache';
import { db } from '@/db';
import { leads, leadFotos, leadPipelineEventos } from '@/db/schema';
import { getTenantBySlug } from '@/lib/funnel/public-queries';
import { procesarLead } from '@/lib/funnel/orchestrator';

const MAX_FOTOS = 4;
const MAX_FOTO_BYTES = 6 * 1024 * 1024; // 6 MB por foto

const crearLeadSchema = z.object({
  nombre: z.string().trim().min(2, 'El nombre es obligatorio'),
  email: z.string().trim().email('Introduce un email válido'),
  telefono: z
    .string()
    .trim()
    .regex(/^[+\d\s\-().]{7,20}$/, 'Introduce un teléfono válido'),
  consentPrivacidad: z.boolean(),
  consentContratacion: z.boolean(),
});

export type CrearLeadInput = z.input<typeof crearLeadSchema>;
export type CrearLeadResult =
  | { ok: true; leadId: string }
  | { ok: false; error: string };

export async function crearLead(slug: string, input: CrearLeadInput): Promise<CrearLeadResult> {
  const parsed = crearLeadSchema.safeParse(input);
  if (!parsed.success) {
    return { ok: false, error: parsed.error.issues[0]?.message ?? 'Datos inválidos.' };
  }
  const data = parsed.data;

  // RF-LEG-01: los dos consentimientos son obligatorios para iniciar el funnel.
  if (!data.consentPrivacidad || !data.consentContratacion) {
    return { ok: false, error: 'Debes aceptar la política de privacidad y las condiciones.' };
  }

  // El lead se atribuye al reformista dueño del funnel (slug de la URL pública).
  const tenant = await getTenantBySlug(slug);
  if (!tenant) {
    return { ok: false, error: 'No hemos podido identificar al reformista. Recarga la página.' };
  }

  const [lead] = await db
    .insert(leads)
    .values({
      tenantId: tenant.id,
      nombre: data.nombre,
      email: data.email,
      telefono: data.telefono,
      consentPrivacidad: data.consentPrivacidad,
      consentContratacion: data.consentContratacion,
      pipelineStage: 'form_completado',
      estado: 'nuevo',
    })
    .returning({ id: leads.id });

  await db.insert(leadPipelineEventos).values({
    leadId: lead.id,
    stage: 'form_completado',
    metadata: { origen: 'landing' },
  });

  return { ok: true, leadId: lead.id };
}

const TIPOS = ['cocina', 'bano', 'salon', 'comedor', 'integral', 'otro'] as const;
const CALIDADES = ['basica', 'media', 'premium'] as const;

async function fileToDataUri(file: File): Promise<string | null> {
  if (file.size === 0 || file.size > MAX_FOTO_BYTES) return null;
  if (!file.type.startsWith('image/')) return null;
  const buffer = Buffer.from(await file.arrayBuffer());
  return `data:${file.type};base64,${buffer.toString('base64')}`;
}

// Paso 3 del funnel: el cliente sube fotos y confirma los datos clave de la reforma.
// Guardamos las fotos como data URI (no hay storage externo en esta fase) y disparamos
// el orquestador que simula la llamada/render y calcula el presupuesto real.
export async function guardarDetallesYFotos(leadId: string, formData: FormData): Promise<void> {
  const [lead] = await db.select().from(leads).where(eq(leads.id, leadId)).limit(1);
  if (!lead) throw new Error('Solicitud no encontrada.');
  const tenantId = lead.tenantId;

  const tipoRaw = String(formData.get('tipoReforma') ?? '');
  const calidadRaw = String(formData.get('calidad') ?? '');
  const m2Raw = Number(formData.get('m2'));
  const provincia = String(formData.get('provincia') ?? '').trim() || null;

  const tipoReforma = (TIPOS as readonly string[]).includes(tipoRaw)
    ? (tipoRaw as (typeof TIPOS)[number])
    : 'otro';
  const calidadGlobal = (CALIDADES as readonly string[]).includes(calidadRaw)
    ? (calidadRaw as (typeof CALIDADES)[number])
    : 'media';
  const m2Suelo = Number.isFinite(m2Raw) && m2Raw > 0 ? m2Raw : null;

  const urgenciaRaw = String(formData.get('urgencia') ?? '');
  const urgencia = (['alta', 'media', 'baja'] as const).includes(urgenciaRaw as 'alta')
    ? (urgenciaRaw as 'alta' | 'media' | 'baja')
    : null;
  const targetEuros = Number(formData.get('presupuestoTarget'));
  const presupuestoTarget =
    Number.isFinite(targetEuros) && targetEuros > 0 ? Math.round(targetEuros * 100) : null;
  const estructural = formData.get('estructural') === 'on';
  const tasteText = String(formData.get('tasteText') ?? '').trim() || null;

  const archivos = formData.getAll('fotos').filter((f): f is File => f instanceof File);
  const dataUris: string[] = [];
  for (const file of archivos.slice(0, MAX_FOTOS)) {
    const uri = await fileToDataUri(file);
    if (uri) dataUris.push(uri);
  }

  if (dataUris.length > 0) {
    await db.insert(leadFotos).values(
      dataUris.map((url, orden) => ({ leadId, url, orden }))
    );
  }

  await db
    .update(leads)
    .set({
      tipoReforma,
      calidadGlobal,
      m2Suelo,
      provincia,
      urgencia,
      presupuestoTarget,
      estructural,
      tasteText,
      pipelineStage: 'fotos_subidas',
      updatedAt: new Date(),
    })
    .where(and(eq(leads.id, leadId), eq(leads.tenantId, tenantId)));

  await db.insert(leadPipelineEventos).values({
    leadId,
    stage: 'fotos_subidas',
    metadata: { fotos: dataUris.length },
  });

  // Dispara el resto del pipeline (llamada simulada → render → presupuesto real → WhatsApp).
  await procesarLead(leadId);

  revalidatePath('/panel');
  redirect(`/solicitud/${leadId}/estado`);
}
