// POST /api/algo/generate
// Turns a plain-English algo name + description into a declarative rule spec
// using Lovable AI Gateway. The client stores the spec locally and the
// browser strategy engine evaluates it against Delta candles. No code is
// executed server-side; the response shape is a validated JSON rule set.

import { createFileRoute } from "@tanstack/react-router";

const CORS = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "POST, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
} as const;

function json(body: unknown, status = 200) {
  return new Response(JSON.stringify(body), {
    status,
    headers: { "Content-Type": "application/json", ...CORS },
  });
}

const SYSTEM = `You are a quantitative trading assistant. Convert the user's plain-English trading idea into a strict JSON rule spec that a runtime evaluator can execute.

Available indicators (exact names — do NOT invent):
- rsi                 // 0..100
- ema_fast_gt_slow    // 1 if EMA20>EMA50 else 0
- macd_hist           // signed number
- price_vs_bb_upper   // 1 if close>=upper Bollinger band else 0
- price_vs_bb_lower   // 1 if close<=lower Bollinger band else 0

Ops: ">", "<", ">=", "<=", "=="

Return ONLY valid JSON, no prose, matching this shape:
{
  "label": string,                       // short human name
  "timeframe": "15m" | "1h" | "any",
  "confidence": number,                  // 0.5..0.9
  "side_rules": {
    "long":  [ { "indicator": string, "op": string, "value": number }, ... ],
    "short": [ { "indicator": string, "op": string, "value": number }, ... ]
  }
}
Each side is AND-ed. At least one side must have >=1 rule. Keep rules simple (2-4 per side).`;

export const Route = createFileRoute("/api/algo/generate")({
  server: {
    handlers: {
      OPTIONS: async () => new Response(null, { status: 204, headers: CORS }),

      POST: async ({ request }) => {
        const apiKey = process.env.LOVABLE_API_KEY;
        if (!apiKey) return json({ error: "LOVABLE_API_KEY missing" }, 500);

        let body: { name?: string; description?: string };
        try {
          body = await request.json();
        } catch {
          return json({ error: "Invalid JSON body" }, 400);
        }
        const name = (body.name ?? "").trim();
        const description = (body.description ?? "").trim();
        if (!name) return json({ error: "name is required" }, 400);

        const userMsg = `Algo name: ${name}\nDescription: ${description || "(none provided — infer sensible defaults from the name)"}\nReturn the JSON spec now.`;

        try {
          const r = await fetch("https://ai.gateway.lovable.dev/v1/chat/completions", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              "Lovable-API-Key": apiKey,
              "X-Lovable-AIG-SDK": "raw-fetch",
            },
            body: JSON.stringify({
              model: "google/gemini-3-flash-preview",
              response_format: { type: "json_object" },
              messages: [
                { role: "system", content: SYSTEM },
                { role: "user", content: userMsg },
              ],
            }),
          });

          if (r.status === 429) return json({ error: "AI rate-limited, please retry shortly" }, 429);
          if (r.status === 402) return json({ error: "AI credits exhausted for this workspace" }, 402);
          if (!r.ok) {
            const t = await r.text().catch(() => "");
            return json({ error: `AI gateway ${r.status}`, detail: t.slice(0, 300) }, 502);
          }
          const j = (await r.json()) as {
            choices?: Array<{ message?: { content?: string } }>;
          };
          const text = j.choices?.[0]?.message?.content ?? "";
          let spec: unknown;
          try {
            spec = JSON.parse(text);
          } catch {
            // Some models wrap JSON in ```json fences — strip and retry
            const stripped = text.replace(/^```(?:json)?/i, "").replace(/```$/, "").trim();
            spec = JSON.parse(stripped);
          }
          return json({ spec, name, description });
        } catch (e) {
          return json(
            { error: e instanceof Error ? e.message : "AI generation failed" },
            502,
          );
        }
      },
    },
  },
});
