import { NextRequest, NextResponse } from "next/server";

interface Issue {
  nodeId?: string;
  nodeLabel?: string;
  severity: "error" | "warning" | "tip";
  message: string;
  fix: string;
}

export async function POST(req: NextRequest) {
  const { nodes, edges } = await req.json();
  const issues: Issue[] = [];

  const nodeMap = new Map(nodes.map((n: any) => [n.id, n]));
  const sourceIds = new Set(edges.map((e: any) => e.source));
  const targetIds = new Set(edges.map((e: any) => e.target));

  // ── 1. Must have exactly one start node ─────────────────────
  const startNodes = nodes.filter((n: any) => n.data?.kind === "start");
  if (startNodes.length === 0) {
    issues.push({ severity: "error", message: "No Trigger (Start) node found", fix: "Add a Trigger block from the left panel — it's where your flow begins." });
  } else if (startNodes.length > 1) {
    issues.push({ severity: "warning", message: `You have ${startNodes.length} Start nodes`, fix: "Only one Start node is used. Delete the extras." });
  }

  // ── 2. Must have at least one end node ──────────────────────
  const endNodes = nodes.filter((n: any) => n.data?.kind === "end");
  if (endNodes.length === 0) {
    issues.push({ severity: "error", message: "No End node found", fix: "Add an End block to mark where the conversation finishes." });
  }

  // ── 3. Orphaned nodes (no connections at all) ────────────────
  for (const node of nodes) {
    if (node.data?.kind === "start") continue;
    const hasIn  = targetIds.has(node.id);
    const hasOut = sourceIds.has(node.id) || node.data?.kind === "end";
    if (!hasIn) {
      issues.push({ nodeId: node.id, nodeLabel: node.data?.label, severity: "warning",
        message: `"${node.data?.label}" has no incoming connection`,
        fix: "Connect an arrow from a previous block into this one." });
    }
    if (!hasOut && node.data?.kind !== "end") {
      issues.push({ nodeId: node.id, nodeLabel: node.data?.label, severity: "warning",
        message: `"${node.data?.label}" has no outgoing connection`,
        fix: "Drag an arrow from this block to the next step, or add an End block." });
    }
  }

  // ── 4. Empty message content ─────────────────────────────────
  for (const node of nodes) {
    const d = node.data;
    if (d?.kind === "message" && !d?.content?.trim()) {
      issues.push({ nodeId: node.id, nodeLabel: d.label, severity: "error",
        message: `"${d.label}" has no message text`,
        fix: "Click the block and write your WhatsApp message in the editor, or use AI Generate." });
    }
    if (d?.kind === "ai_response" && !d?.aiSystemPrompt?.trim()) {
      issues.push({ nodeId: node.id, nodeLabel: d.label, severity: "warning",
        message: `"${d.label}" has no AI instructions`,
        fix: "Click the block → AI Generate tab → let Claude write the instructions, or write them manually." });
    }
    if (d?.kind === "buttons" && (!d?.buttons || d.buttons.length === 0)) {
      issues.push({ nodeId: node.id, nodeLabel: d.label, severity: "error",
        message: `"${d.label}" has no buttons added`,
        fix: "Click the block and add at least one button option (minimum 2 recommended)." });
    }
    if (d?.kind === "condition" && (!d?.branches || d.branches.length === 0)) {
      issues.push({ nodeId: node.id, nodeLabel: d.label, severity: "warning",
        message: `"${d.label}" has no branches defined`,
        fix: "Click the block and add branches — each branch is a possible patient response." });
    }
    if (d?.kind === "save_var" && !d?.varName?.trim()) {
      issues.push({ nodeId: node.id, nodeLabel: d.label, severity: "warning",
        message: `"${d.label}" has no variable name`,
        fix: "Click the block and give the variable a name like 'preferred_time'." });
    }
  }

  // ── 5. Buttons missing their connections ─────────────────────
  for (const node of nodes) {
    if (node.data?.kind !== "buttons") continue;
    const btns: any[] = node.data?.buttons || [];
    for (const btn of btns) {
      const hasEdge = edges.some((e: any) => e.source === node.id && e.sourceHandle === btn.id);
      if (!hasEdge) {
        issues.push({ nodeId: node.id, nodeLabel: node.data.label, severity: "tip",
          message: `Button "${btn.text}" in "${node.data.label}" is not connected`,
          fix: `Drag an arrow from the "${btn.text}" button handle to the next step for that choice.` });
      }
    }
  }

  // ── 6. Flow too short ────────────────────────────────────────
  if (nodes.filter((n: any) => n.data?.kind !== "start" && n.data?.kind !== "end").length < 2) {
    issues.push({ severity: "tip", message: "Flow seems very short",
      fix: "Consider adding more steps — a message, a button choice, and an AI reply make a complete conversation." });
  }

  // ── 7. No human escalation path ─────────────────────────────
  const hasHumanEsc = nodes.some((n: any) =>
    n.data?.content?.toLowerCase().includes("call") ||
    n.data?.content?.toLowerCase().includes("phone") ||
    n.data?.aiSystemPrompt?.toLowerCase().includes("human") ||
    n.data?.label?.toLowerCase().includes("escalat")
  );
  if (!hasHumanEsc && nodes.length > 5) {
    issues.push({ severity: "tip", message: "No human escalation path detected",
      fix: "Consider adding a step where frustrated patients can request to speak to a person — it builds trust." });
  }

  const score = Math.max(0, 100
    - issues.filter(i => i.severity === "error").length * 25
    - issues.filter(i => i.severity === "warning").length * 10
    - issues.filter(i => i.severity === "tip").length * 3
  );

  return NextResponse.json({
    issues,
    score,
    ready: issues.filter(i => i.severity === "error").length === 0,
    summary: {
      errors:   issues.filter(i => i.severity === "error").length,
      warnings: issues.filter(i => i.severity === "warning").length,
      tips:     issues.filter(i => i.severity === "tip").length,
    },
  });
}
