import Anthropic from "@anthropic-ai/sdk";
import { ProposalContentSchema, type ProposalContent } from "./schema";
import type { OfferEditorData } from "@/lib/offer-queries";
import type { Client, Lead, ClientTranscript } from "@/db/schema";

const MODEL = "claude-opus-4-8";

type AgentInput = {
  // lead o cliente (uno dei due)
  lead?: Pick<Lead, "id" | "name" | "email" | "company" | "notes">;
  client?: Pick<Client, "id" | "name" | "brand_name" | "brief">;
  transcripts: Pick<ClientTranscript, "title" | "content" | "call_date">[];
  offer: OfferEditorData;
  model?: string;
};

function buildSystemPrompt(): string {
  return `Sei un consulente senior di brand e business strategy con 10+ anni di esperienza.
Il tuo compito è analizzare i transcript di call discovery con un cliente e generare il
contenuto di un preventivo professionale in italiano.

REGOLE FONDAMENTALI:
- Usa SOLO informazioni reali estratte dai transcript. Non inventare problemi, soluzioni o citazioni.
- Le citazioni (quote) nei nodi problema devono essere verbatim — parole esatte dette dal cliente.
- I problemi devono emergere dalle parole del cliente, non da assunzioni tue.
- Le soluzioni devono specchiare i problemi (stessa sequenza 01–05) e descrivere la trasformazione concreta.
- Il tono è professionale ma diretto, mai generico. Usa il lessico del settore del cliente.
- Non includere prezzi o importi nel contenuto generato — quelli vengono dal DB dell'offerta.
- Rispondi SOLO con JSON valido, nessun testo extra prima o dopo.`;
}

function buildUserPrompt(input: AgentInput): string {
  const subject = input.client
    ? `Cliente: ${input.client.name} (brand: ${input.client.brand_name})\nBrief: ${input.client.brief}`
    : `Lead: ${input.lead?.name}${input.lead?.company ? ` — ${input.lead.company}` : ""}${input.lead?.notes ? `\nNote: ${input.lead.notes}` : ""}`;

  const transcriptBlocks = input.transcripts
    .map(
      (t, i) =>
        `=== TRANSCRIPT ${i + 1} — ${t.call_date}${t.title ? ` (${t.title})` : ""} ===\n${t.content}`
    )
    .join("\n\n");

  const offerDescription = `Offerta: ${input.offer.macro.public_name}
Descrizione: ${input.offer.macro.description ?? "—"}
Promessa di trasformazione: ${input.offer.macro.transformation_promise ?? "—"}
Tier disponibili: ${input.offer.tiers.map((t) => `${t.tier_letter} (${t.public_name})`).join(", ")}`;

  return `${subject}

${offerDescription}

TRANSCRIPT DELLE CALL:
${transcriptBlocks || "(nessun transcript disponibile — genera contenuto basato sul brief)"}

Genera il contenuto del preventivo come JSON. Segui ESATTAMENTE questo schema TypeScript:

{
  vision: { headline: string, body: string },
  problems: Array<{
    id: string,          // "01" | "02" | ... | "05"
    title: string,       // titolo della slide problema
    subtitle: string,    // es. "LA VOCE" — tema macro
    body: string,        // 2-3 frasi descrittive
    risk: string,        // testo box "IL RISCHIO" — conseguenza se non si risolve
    quote: string,       // citazione verbatim dal transcript
    quoteAttribution: string // "NOME · DISCOVERY YYYY-MM-DD"
  }>,  // 3–5 problemi
  problemSynthesis: {
    rootCause: string,   // la domanda strategica comune
    nodeLabels: string[] // 5 label brevi per il diagramma
  },
  solutions: Array<{
    id: string,               // specchia il problem node
    title: string,
    subtitle: string,         // es. "SOLUZIONE 01 · LA VOCE"
    transformation: string,   // testo box "LA TRASFORMAZIONE"
    throughWhat: string[]     // 3 bullet "ATTRAVERSO COSA"
  }>,
  solutionSynthesis: {
    direction: string,
    elevations: Array<{ id: string, label: string }> // 5 elementi
  },
  scope: {
    scopeTitle: string,
    scopeBody: string,
    objectives: string[]  // 3–5 obiettivi misurabili
  },
  deliverables: {
    deliverables: string[],  // output principali (tier-agnostic)
    outOfScope: string[]     // 3–5 elementi esclusi
  },
  timeline: {
    totalWeeks: number,
    phases: Array<{
      label: string,
      startWeek: number,
      endWeek: number,
      color: "cyan" | "purple" | "green"
    }>,
    disclaimer: string
  },
  stagesRecap: {
    stages: Array<{
      number: string,      // "01" | "02" | "03"
      tierLetter: string,  // "A" | "B" | "C"
      label: string,       // es. "OPZIONE A – AUDIT"
      headline: string,    // es. "Si capisce."
      body: string,
      deliverable: string
    }>
  },
  comparisonMatrix: Array<{
    component: string,
    description: string,
    inA: boolean,
    inB: boolean,
    inC: boolean
  }>  // 4–10 righe
}`;
}

export async function generateProposalContent(
  input: AgentInput
): Promise<{ content: ProposalContent; rawJson: string }> {
  const apiKey = process.env.ANTHROPIC_API_KEY;
  if (!apiKey) throw new Error("ANTHROPIC_API_KEY non configurata");

  const client = new Anthropic({ apiKey });

  const message = await client.messages.create({
    model: input.model ?? MODEL,
    max_tokens: 8192,
    system: buildSystemPrompt(),
    messages: [{ role: "user", content: buildUserPrompt(input) }],
  });

  const rawText =
    message.content[0].type === "text" ? message.content[0].text : "";

  // Estrae il JSON dalla risposta (gestisce eventuale wrapping in ```)
  const jsonMatch = rawText.match(/```(?:json)?\s*([\s\S]*?)\s*```/) ||
    rawText.match(/(\{[\s\S]*\})/);
  const jsonStr = jsonMatch ? jsonMatch[1] : rawText;

  let parsed: unknown;
  try {
    parsed = JSON.parse(jsonStr);
  } catch {
    throw new Error(`L'AI ha prodotto JSON non valido: ${rawText.slice(0, 200)}`);
  }

  const result = ProposalContentSchema.safeParse(parsed);
  if (!result.success) {
    throw new Error(
      `Contenuto AI non valido: ${result.error.issues.map((i) => i.message).join("; ")}`
    );
  }

  return { content: result.data, rawJson: jsonStr };
}
