import { asc, eq } from 'drizzle-orm';
import { renderToBuffer } from '@react-pdf/renderer';
import { db } from '@/db';
import { leads, leadFotos, leadNotas } from '@/db/schema';
import type { Lead, LeadFoto, LeadNota } from '@/db/schema';
import { getTenantPerfilById, type TenantPerfil } from '@/db/tenant-queries';
import { TIPO_LABEL } from '@/lib/funnel';
import { PresupuestoDoc, type ZonaPdf } from '@/lib/pdf/PresupuestoDoc';
import { construirDescripcionRender, resolverImagenPdf } from '@/lib/pdf/render-info';
import type { BudgetResult } from '@/budget/types';
import type { AbstractedPreferences } from '@/lib/voice/preferences';

export type PresupuestoPdf = {
  buffer: Buffer;
  filename: string;
  lead: Lead;
  tenant: TenantPerfil;
};

type Tipo = NonNullable<Lead['tipoReforma']>;

// Agrupa fotos y notas por zona (con fallback al tipo de reforma del lead) y devuelve, por zona,
// la primera foto "antes" y la primera "despues" convertidas a data URI que @react-pdf puede
// incrustar, más las notas de texto de esa zona.
async function construirZonas(
  fotos: LeadFoto[],
  notas: LeadNota[],
  tipoLead: Tipo,
): Promise<ZonaPdf[]> {
  const zonas = new Map<Tipo, { antes: LeadFoto[]; despues: LeadFoto[]; notas: string[] }>();
  const slot = (zona: Tipo) => {
    let s = zonas.get(zona);
    if (!s) {
      s = { antes: [], despues: [], notas: [] };
      zonas.set(zona, s);
    }
    return s;
  };

  for (const f of fotos) {
    const zona = (f.zona ?? tipoLead) as Tipo;
    slot(zona)[f.momento].push(f);
  }
  for (const n of notas) {
    const texto = n.texto.trim();
    if (texto) slot((n.zona ?? tipoLead) as Tipo).notas.push(texto);
  }

  const resultado: ZonaPdf[] = [];
  for (const [zona, data] of zonas) {
    const [antesSrc, despuesSrc] = await Promise.all([
      resolverImagenPdf(data.antes[0]?.url ?? null, { formato: 'jpeg', maxAncho: 1000 }),
      resolverImagenPdf(data.despues[0]?.url ?? null, { formato: 'jpeg', maxAncho: 1000 }),
    ]);
    if (!antesSrc && !despuesSrc && data.notas.length === 0) continue;
    resultado.push({ zonaLabel: TIPO_LABEL[zona], antesSrc, despuesSrc, notas: data.notas });
  }
  return resultado;
}

// Arma el PDF del presupuesto de un lead: desglose real + render + galería antes/después y notas
// por zona. Carga el lead por id sin scoping de tenant (uso interno: lo llaman el route del panel
// y la finalización pública), por eso resuelve el perfil del reformista vía getTenantPerfilById.
export async function construirPresupuestoPdf(leadId: string): Promise<PresupuestoPdf | null> {
  const [lead] = await db.select().from(leads).where(eq(leads.id, leadId)).limit(1);
  if (!lead) return null;

  const [fotos, notas, tenant] = await Promise.all([
    db.select().from(leadFotos).where(eq(leadFotos.leadId, leadId)).orderBy(asc(leadFotos.orden)),
    db.select().from(leadNotas).where(eq(leadNotas.leadId, leadId)).orderBy(asc(leadNotas.createdAt)),
    getTenantPerfilById(lead.tenantId),
  ]);

  const tipo: Tipo = lead.tipoReforma ?? 'otro';
  const snapshot = lead.desgloseSnapshot as { result: BudgetResult } | null;
  const desglose = snapshot?.result ?? null;
  const prefs = lead.preferencesSnapshot as AbstractedPreferences | null;

  const [logoSrc, renderSrc, zonas] = await Promise.all([
    resolverImagenPdf(tenant.logoUrl, { formato: 'png', maxAncho: 400 }),
    resolverImagenPdf(lead.renderUrl, { formato: 'jpeg', maxAncho: 1400 }),
    construirZonas(fotos, notas, tipo),
  ]);

  const render = renderSrc
    ? {
        imagenSrc: renderSrc,
        descripcion: construirDescripcionRender({
          calidad: lead.calidadGlobal,
          materiales: desglose?.materialesRender ?? [],
          estilo: prefs?.estiloRender ?? [],
        }),
      }
    : null;

  const buffer = await renderToBuffer(
    PresupuestoDoc({
      empresa: tenant,
      cliente: { nombre: lead.nombre, telefono: lead.telefono, provincia: lead.provincia },
      reforma: { tipoLabel: lead.tipoReforma ? TIPO_LABEL[tipo] : 'Reforma', fecha: lead.createdAt },
      desglose,
      logoSrc,
      render,
      zonas,
    }),
  );

  const slug = lead.nombre.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
  return { buffer, filename: `presupuesto-${slug || lead.id}.pdf`, lead, tenant };
}
