// pages/api/generate-svg-logo.ts
import type { NextApiRequest, NextApiResponse } from "next";
import OpenAI from "openai";
import { optimize } from "svgo";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });

const SVGO_CONFIG = {
  multipass: true,
  plugins: [
    "removeDoctype",
    "removeXMLProcInst",
    "removeComments",
    "removeMetadata",
    "cleanupAttrs",
    "minifyStyles",
    "cleanupIds",
    "removeScriptElement",
    "removeUnknownsAndDefaults",
    "removeUselessDefs",
    "convertPathData",
    "mergePaths",
  ],
};

// Basic guardrail: reject trivial single-shape logos
function validateSvg(svg: string): { ok: boolean; reason?: string } {
  const s = svg.replace(/\s+/g, " ").toLowerCase();

  // must be single <svg> wrapper
  if (!/^<svg[\s\S]*<\/svg>\s*$/.test(s)) return { ok: false, reason: "not single svg" };

  // count primitives
  const paths = (s.match(/<path\b/g) || []).length;
  const circles = (s.match(/<circle\b/g) || []).length;
  const ellipses = (s.match(/<ellipse\b/g) || []).length;
  const rects = (s.match(/<rect\b/g) || []).length;
  const polys = (s.match(/<(polygon|polyline)\b/g) || []).length;

  // Reject “one primitive only” cases, e.g., just a circle
  const totalPrimitives = paths + circles + ellipses + rects + polys;
  if (totalPrimitives <= 1) return { ok: false, reason: "single primitive" };

  // If no paths at all, likely too trivial for an organic bean
  if (paths < 1) return { ok: false, reason: "no paths" };

  // Reject pure circle/ellipse primary shapes (bean shouldn’t be a perfect circle)
  if (paths === 0 && (circles + ellipses) >= 1) return { ok: false, reason: "circle/ellipse only" };

  // No <text>, <image>, <foreignObject>, external refs
  if (/(<text|<image|<foreignobject|xlink:href=|href=("|')http)/i.test(svg)) {
    return { ok: false, reason: "disallowed content" };
  }

  return { ok: true };
}

function buildSystemPrompt(colorList: string, complexity: string) {
  return [
    "You output ONLY valid SVG markup. No prose, no backticks.",
    'Return a single <svg> element with viewBox="0 0 1024 1024". Omit width/height.',
    "Use only vector shapes: <g>, <path>, <rect>, <circle>, <ellipse>, <polygon>, <polyline>, <line>, <defs>, <linearGradient>, <radialGradient>, <clipPath>.",
    "ABSOLUTELY NO <text>, NO <image>, NO <foreignObject>, NO external links, NO scripts.",
    "All fills and strokes must use ONLY these hex colors: " + colorList + ".",
    "Design: logo mark (no words). Clean, balanced, recognizable at small sizes.",
    `Complexity: ${complexity}.`,
    "Leave natural padding (~6–10% inside the artboard).",
  ].join("\n");
}

function buildUserPrompt(subject: string, enforceBean = false) {
  // For coffee bean (or similar organic forms), specify anatomy and anti-circle constraints
  const beanSpec = enforceBean
    ? [
        "Subject: a coffee bean silhouette (not a perfect circle).",
        "Requirements:",
        "- Overall outline is an ellipse-like bean shape, taller than wide (portrait), aspect ratio ~0.75–0.9.",
        "- Include a curved central groove path (S-curve), slightly offset, not perfectly straight.",
        "- Use <path> for the outer silhouette and groove (avoid a single <circle> or <ellipse> as the main body).",
        "- You may add subtle highlights/shadows as additional paths or simple gradients; keep it minimalist.",
        "- Do NOT use realistic photos; pure vector only.",
      ].join("\n")
    : "";

  return [
    `Create a vector logo mark for: ${subject}.`,
    beanSpec,
    "Return ONLY the SVG markup. No explanations.",
  ].filter(Boolean).join("\n");
}

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
    if (req.method !== "POST") return res.status(405).end();

    const {
      prompt,
      palette = {},
      model = "gpt-4.1",
      complexity = "medium", // "simple" | "medium" | "complex"
      subjectHint = "coffee bean",      // helps trigger anatomy rules
      maxRetries = 2,
    } = req.body || {};

    if (!prompt) return res.status(400).json({ error: "Missing prompt" });

    // Palette → color allowlist
    const colors: string[] = [
      palette.primary, palette.secondary, palette.accent, palette.highlight,
      palette.neutral, palette.surface, palette.textLight, palette.textDark,
      "#000000", "#ffffff",
    ].filter(Boolean);
    const colorList = colors.length ? colors.join(", ") : "#111827, #f8fafc, #2563eb, #10b981";

    const system = buildSystemPrompt(colorList, complexity);

    let svg = "";
    let attempt = 0;
    let lastReason = "";

    while (attempt <= maxRetries) {
      const enforce = attempt > 0 || /coffee\s*bean/i.test(prompt) || /bean/i.test(subjectHint);
      const user = buildUserPrompt(prompt, enforce);

      const resp = await openai.chat.completions.create({
        model,
        temperature: 0.5,
        messages: [
          { role: "system", content: system },
          { role: "user", content: user },
        ],
      });

      svg = resp.choices?.[0]?.message?.content?.trim() || "";
      svg = svg.replace(/^```(?:svg)?/i, "").replace(/```$/i, "").trim();

      // Optimize
      const optimized = optimize(svg, SVGO_CONFIG) as any;
      if (!optimized?.data) {
        lastReason = "svgo failed";
      } else {
        svg = optimized.data;
        // Enforce viewBox; remove width/height
        svg = svg.replace(/<svg([^>]*?)>/i, (m, attrs) => {
          let a = attrs.replace(/\swidth="[^"]*"/i, "").replace(/\sheight="[^"]*"/i, "");
          if (!/viewbox="/i.test(a)) a += ' viewBox="0 0 1024 1024"';
          return `<svg${a}>`;
        });

        const v = validateSvg(svg);
        if (v.ok) {
          return res.status(200).json({ svg });
        }
        lastReason = v.reason || "invalid";
      }

      attempt++;
    }

    return res.status(422).json({ error: `Could not generate non-trivial SVG (${lastReason}). Try rephrasing prompt.` });
  } catch (e: any) {
    console.error(e);
    return res.status(500).json({ error: e?.message ?? "Internal error" });
  }
}
