/**
 * /api/tip-llm — Guided Inference API for tip-llm-v1
 *
 * Endpoints:
 *   POST /api/tip-llm/infer          — general inference (any task)
 *   POST /api/tip-llm/research-plan  — generate search/crawl plan
 *   POST /api/tip-llm/extract        — extract facts from HTML/text
 *   POST /api/tip-llm/finding        — produce a finding from evidence
 *   GET  /api/tip-llm/health         — model health check
 */

import { Router, type Request, type Response } from "express";
import {
  tipLlmInfer,
  tipLlmResearchPlan,
  tipLlmExtract,
  tipLlmFinding,
  checkTipLlmHealth,
  type TipLlmInput,
  type TipLlmTask,
} from "../llm/tip-llm-guided";

export const tipLlmRouter = Router();

const VALID_TASKS: TipLlmTask[] = ["research_plan", "extract", "finding"];

// ── Health ─────────────────────────────────────────────────────────────────

tipLlmRouter.get("/health", async (_req: Request, res: Response) => {
  const result = await checkTipLlmHealth();
  res.status(result.ok ? 200 : 503).json(result);
});

// ── General infer ──────────────────────────────────────────────────────────

tipLlmRouter.post("/infer", async (req: Request, res: Response) => {
  const { task, text, url, vendor, product, context } = req.body as {
    task?: string;
    text?: string;
    url?: string;
    vendor?: string;
    product?: string;
    context?: string;
  };

  if (!task || !VALID_TASKS.includes(task as TipLlmTask)) {
    res.status(400).json({ error: `task is required and must be one of: ${VALID_TASKS.join(", ")}` });
    return;
  }
  if (text && text.length > 8000) {
    res.status(400).json({ error: "text must be <= 8000 characters" });
    return;
  }

  const input: TipLlmInput = {
    task: task as TipLlmTask,
    text,
    url,
    vendor,
    product,
    context,
  };

  const result = await tipLlmInfer(input);
  res.json({ success: true, data: result });
});

// ── Research plan ──────────────────────────────────────────────────────────

tipLlmRouter.post("/research-plan", async (req: Request, res: Response) => {
  const { vendor, product, context } = req.body as {
    vendor?: string;
    product?: string;
    context?: string;
  };

  if (!vendor || !product) {
    res.status(400).json({ error: "vendor and product are required" });
    return;
  }

  const result = await tipLlmResearchPlan(vendor, product, context);
  res.json({ success: true, data: result });
});

// ── Extract ────────────────────────────────────────────────────────────────

tipLlmRouter.post("/extract", async (req: Request, res: Response) => {
  const { text, url, vendor, product } = req.body as {
    text?: string;
    url?: string;
    vendor?: string;
    product?: string;
  };

  if (!text || !url) {
    res.status(400).json({ error: "text and url are required" });
    return;
  }
  if (text.length > 8000) {
    res.status(400).json({ error: "text must be <= 8000 characters" });
    return;
  }

  const result = await tipLlmExtract(text, url, vendor, product);
  res.json({ success: true, data: result });
});

// ── Finding ────────────────────────────────────────────────────────────────

tipLlmRouter.post("/finding", async (req: Request, res: Response) => {
  const { text, vendor, product, url } = req.body as {
    text?: string;
    vendor?: string;
    product?: string;
    url?: string;
  };

  if (!text || !vendor || !product) {
    res.status(400).json({ error: "text, vendor and product are required" });
    return;
  }
  if (text.length > 8000) {
    res.status(400).json({ error: "text must be <= 8000 characters" });
    return;
  }

  const result = await tipLlmFinding(text, vendor, product, url);
  res.json({ success: true, data: result });
});
