import { and, asc, eq } from 'drizzle-orm';
import { db } from '@/db';
import {
  tenants,
  leads,
  leadFotos,
  leadPipelineEventos,
  testimonios,
  testimonioFotos,
  galeriaFotos,
} from '@/db/schema';

export type PublicTenant = {
  id: string;
  slug: string;
  nombreEmpresa: string;
  logoUrl: string | null;
  seoTitle: string | null;
  seoDescription: string | null;
  aboutEnabled: boolean;
  aboutFotoUrl: string | null;
  aboutTexto: string | null;
  aniosExperiencia: number | null;
  themePreset: string;
  themeColor: string | null;
};

const TENANT_PUBLIC_COLUMNS = {
  id: tenants.id,
  slug: tenants.slug,
  nombreEmpresa: tenants.nombreEmpresa,
  logoUrl: tenants.logoUrl,
  seoTitle: tenants.seoTitle,
  seoDescription: tenants.seoDescription,
  aboutEnabled: tenants.aboutEnabled,
  aboutFotoUrl: tenants.aboutFotoUrl,
  aboutTexto: tenants.aboutTexto,
  aniosExperiencia: tenants.aniosExperiencia,
  themePreset: tenants.themePreset,
  themeColor: tenants.themeColor,
} as const;

export type PublicGaleriaFoto = {
  id: string;
  url: string;
  titulo: string | null;
};

// Galería de trabajos publicada por el reformista, para mostrar en su landing.
export async function getGaleria(tenantId: string): Promise<PublicGaleriaFoto[]> {
  const rows = await db
    .select({ id: galeriaFotos.id, url: galeriaFotos.url, titulo: galeriaFotos.titulo })
    .from(galeriaFotos)
    .where(eq(galeriaFotos.tenantId, tenantId))
    .orderBy(asc(galeriaFotos.orden), asc(galeriaFotos.createdAt));
  return rows;
}

export type PublicTestimonio = {
  id: string;
  nombre: string;
  contexto: string | null;
  rating: number;
  texto: string;
  fotos: string[];
};

// Testimonios publicados de un reformista, para mostrar en su landing.
export async function getPublishedTestimonios(tenantId: string): Promise<PublicTestimonio[]> {
  const rows = await db
    .select()
    .from(testimonios)
    .where(and(eq(testimonios.tenantId, tenantId), eq(testimonios.estado, 'publicado')))
    .orderBy(asc(testimonios.createdAt));
  if (rows.length === 0) return [];

  const fotos = await db
    .select()
    .from(testimonioFotos)
    .orderBy(asc(testimonioFotos.orden));

  return rows.map((t) => ({
    id: t.id,
    nombre: t.nombre,
    contexto: t.contexto,
    rating: t.rating,
    texto: t.texto,
    fotos: fotos.filter((f) => f.testimonioId === t.id).map((f) => f.url),
  }));
}

// Resuelve el reformista dueño del funnel a partir de su slug público.
// Devuelve null si el slug no corresponde a ningún reformista.
export async function getTenantBySlug(slug: string): Promise<PublicTenant | null> {
  const [row] = await db
    .select(TENANT_PUBLIC_COLUMNS)
    .from(tenants)
    .where(eq(tenants.slug, slug))
    .limit(1);
  return row ?? null;
}

// Lectura del lead para las páginas públicas del funnel (/solicitud/[id]).
// El lead se identifica por su UUID (no enumerable); devolvemos su reformista
// para mostrar el branding correcto sin exponer datos de otros tenants.
export async function getPublicLead(id: string) {
  const [lead] = await db.select().from(leads).where(eq(leads.id, id)).limit(1);
  if (!lead) return null;

  const [[tenant], fotos, eventos] = await Promise.all([
    db.select(TENANT_PUBLIC_COLUMNS).from(tenants).where(eq(tenants.id, lead.tenantId)).limit(1),
    db.select().from(leadFotos).where(eq(leadFotos.leadId, id)).orderBy(asc(leadFotos.orden)),
    db
      .select()
      .from(leadPipelineEventos)
      .where(eq(leadPipelineEventos.leadId, id))
      .orderBy(asc(leadPipelineEventos.occurredAt)),
  ]);

  return { lead, tenant: tenant ?? null, fotos, eventos };
}

// Lectura del lead para el funnel de opinión (/opinion/[id]).
// El lead se identifica por su UUID. Devolvemos el branding del reformista y si
// ya hay un testimonio enviado para no permitir duplicados.
export async function getLeadForReview(id: string) {
  const [lead] = await db
    .select({ id: leads.id, nombre: leads.nombre, tenantId: leads.tenantId })
    .from(leads)
    .where(eq(leads.id, id))
    .limit(1);
  if (!lead) return null;

  const [[tenant], [yaEnviado]] = await Promise.all([
    db.select(TENANT_PUBLIC_COLUMNS).from(tenants).where(eq(tenants.id, lead.tenantId)).limit(1),
    db.select({ id: testimonios.id }).from(testimonios).where(eq(testimonios.leadId, id)).limit(1),
  ]);

  return { lead, tenant: tenant ?? null, yaEnviado: !!yaEnviado };
}

// Verifica que un lead pertenece al tenant indicado (scoping de mutaciones).
export async function leadPerteneceATenant(leadId: string, tenantId: string): Promise<boolean> {
  const [row] = await db
    .select({ id: leads.id })
    .from(leads)
    .where(and(eq(leads.id, leadId), eq(leads.tenantId, tenantId)))
    .limit(1);
  return !!row;
}
