"use server";

import { db } from "@/db";
import { proposals, leads, clients } from "@/db/schema";
import { nanoid } from "nanoid";
import { eq, and, isNull } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { generateProposalContent } from "@/lib/proposal/agent";
import { assembleProposal } from "@/lib/proposal/assemble";
import { getOfferEditorData } from "@/lib/offer-queries";
import { getTranscripts } from "@/lib/lead-service";

async function requireAdmin() {
  const session = await getServerSession(authOptions);
  if (!session) throw new Error("Non autorizzato");
}

// Genera una bozza di preventivo con AI e salva nel DB
export async function generateProposalDraft(formData: FormData) {
  await requireAdmin();

  const leadId = formData.get("lead_id") as string | null;
  const clientId = formData.get("client_id") as string | null;
  const offerMacroId = formData.get("offer_macro_id") as string;

  if (!offerMacroId) throw new Error("offer_macro_id richiesto");
  if (!leadId && !clientId) throw new Error("lead_id o client_id richiesto");

  // Carica dati necessari
  const offer = await getOfferEditorData(offerMacroId);
  if (!offer) throw new Error("Offerta non trovata");

  let lead = undefined;
  let client = undefined;
  let transcripts: Awaited<ReturnType<typeof getTranscripts>> = [];

  if (leadId) {
    const [leadRow] = await db
      .select({ id: leads.id, name: leads.name, email: leads.email, company: leads.company, notes: leads.notes })
      .from(leads)
      .where(eq(leads.id, leadId))
      .limit(1);
    lead = leadRow;
    transcripts = await getTranscripts(leadId);
  } else if (clientId) {
    const [clientRow] = await db
      .select({ id: clients.id, name: clients.name, brand_name: clients.brand_name, brief: clients.brief })
      .from(clients)
      .where(eq(clients.id, clientId))
      .limit(1);
    client = clientRow;
    // Trascrizioni del cliente (via client_id)
    const { clientTranscripts } = await import("@/db/schema");
    const { eq: drizzleEq, desc } = await import("drizzle-orm");
    transcripts = await db
      .select()
      .from(clientTranscripts)
      .where(drizzleEq(clientTranscripts.client_id, clientId))
      .orderBy(desc(clientTranscripts.call_date));
  }

  const MODEL_IDS = {
    opus: "claude-opus-4-8",
    sonnet: "claude-sonnet-4-6",
  } as const;

  const modelKey = (() => {
    const raw = formData.get("model");
    if (raw === "opus" || raw === "sonnet") return raw;
    return "opus" as const;
  })();
  const resolvedModel = MODEL_IDS[modelKey];

  // Chiama agente AI
  const { content: aiContent } = await generateProposalContent({
    lead,
    client,
    transcripts,
    offer,
    model: resolvedModel,
  });

  // Assembla contenuto completo
  const assembled = assembleProposal({
    lead,
    client,
    offer,
    aiContent,
    model: resolvedModel,
  });

  // Salva nel DB
  const id = nanoid();
  const slug = nanoid();
  const title = `${assembled.header.clientName} × ${assembled.header.offerTitle}`;

  await db.insert(proposals).values({
    id,
    slug,
    lead_id: leadId ?? null,
    client_id: clientId ?? null,
    offer_macro_id: offerMacroId,
    title,
    content: assembled as unknown as Record<string, unknown>,
    model: resolvedModel,
    state: "draft",
  });

  revalidatePath("/admin/preventivi");
  redirect(`/admin/preventivi/${id}`);
}

// Pubblica la proposta (draft → published)
export async function publishProposal(id: string) {
  await requireAdmin();

  await db
    .update(proposals)
    .set({ state: "published", updated_at: new Date() })
    .where(and(eq(proposals.id, id), eq(proposals.state, "draft")));

  revalidatePath(`/admin/preventivi/${id}`);
  revalidatePath("/admin/preventivi");
}

// Aggiorna il titolo della proposta
export async function updateProposalTitle(id: string, title: string) {
  await requireAdmin();

  await db
    .update(proposals)
    .set({ title: title.trim(), updated_at: new Date() })
    .where(eq(proposals.id, id));

  revalidatePath(`/admin/preventivi/${id}`);
}

// Elimina una proposta (solo draft)
export async function deleteProposal(id: string) {
  await requireAdmin();

  await db
    .delete(proposals)
    .where(and(eq(proposals.id, id), eq(proposals.state, "draft")));

  revalidatePath("/admin/preventivi");
  redirect("/admin/preventivi");
}
