export default async function handler(req, res) { if (req.method !== "POST") { return res.status(405).json({ error: "Only POST allowed" }); } try { const { anchorCompany, peers, internalData } = req.body || {}; const anchor = String(anchorCompany || "").trim(); const peerList = Array.isArray(peers) ? peers.map(p => String(p || "").trim()).filter(Boolean) : []; if (!anchor) return res.status(400).json({ error: "anchorCompany is required" }); if (peerList.length === 0) return res.status(400).json({ error: "peers[] is required" }); if (peerList.length > 5) return res.status(400).json({ error: "Max 5 peers allowed" }); if (!process.env.OPENAI_API_KEY) { return res.status(500).json({ error: "OPENAI_API_KEY missing" }); } // Internal data is optional const internal = internalData && typeof internalData === "object" ? { ai_talent: Number(internalData.ai_talent), ai_projects: Number(internalData.ai_projects), ai_tools_adoption: Number(internalData.ai_tools_adoption), data_quality: Number(internalData.data_quality) } : null; // Simple clamp helper const clamp = (n) => Math.max(0, Math.min(100, Number.isFinite(n) ? n : 0)); const internalClean = internal ? { ai_talent: clamp(internal.ai_talent), ai_projects: clamp(internal.ai_projects), ai_tools_adoption: clamp(internal.ai_tools_adoption), data_quality: clamp(internal.data_quality) } : null; // Ask OpenAI to return ONLY JSON in strict schema const prompt = { model: "gpt-4.1-mini", input: [ { role: "system", content: "You are DeltaAIQ. Return ONLY valid JSON. No markdown. No extra text. Values must be within 0-100 where applicable." }, { role: "user", content: JSON.stringify({ task: "benchmark_dashboard", anchorCompany: anchor, selectedPeers: peerList, internalData: internalClean, requirements: { summary: { aiq: "0-100 integer", industryPercentile: "0-100 integer", confidence: "Low|Medium|High", confidenceReason: "short sentence", aiqNarrative: "1-2 lines for HR/strategy audience" }, peerStats: { p25: "0-100", median: "0-100", p75: "0-100" }, radar: { labels: ["AI Talent", "Tools Adoption", "Data Foundation", "Governance", "Delivery", "Change Readiness"], selectedAvg: "array of 6 ints 0-100", peerMedian: "array of 6 ints 0-100" }, peerComparison: { labels: "selected peers names array", peerAIQ: "array of AIQ values aligned to labels" }, trend: { days: ["0", "30", "60", "90"], aiq: "array of 4 ints 0-100", targetBand: "array of 4 ints 0-100", note: "one sentence" }, whySimilar: "object map: peerName -> 1-2 line explanation", recommendations: "array of 4-6 items: {priority: P1/P2/P3, theme, action, impact}" } }) } ], max_output_tokens: 900 }; const r = await fetch("https://api.openai.com/v1/responses", { method: "POST", headers: { "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify(prompt) }); if (!r.ok) { const t = await r.text(); return res.status(500).json({ error: "OpenAI error", details: t }); } const payload = await r.json(); const text = payload?.output?.[0]?.content ?.map(c => (c.type === "output_text" ? c.text : "")) .join("") || ""; let parsed; try { parsed = JSON.parse(text); } catch { const m = text.match(/\{[\s\S]*\}/); parsed = m ? JSON.parse(m[0]) : null; } if (!parsed || typeof parsed !== "object") { return res.status(500).json({ error: "Invalid benchmark response" }); } return res.status(200).json(parsed); } catch (err) { return res.status(500).json({ error: "Server error", details: err.message }); } }