/* SkyOps Intelligence — ambient AI woven into the product, not a chat window.
   1. Command line (topbar): ask or instruct in natural language. Commands act on the current screen
      (navigate, filter, create, approve); questions are answered in place, grounded in what's on screen.
   2. Lens: every KPI and table row is explainable — hover ✦ to ask "why", "what to do", "find similar".
   3. Selection: select any text on a page to ask about it.
   4. Core decisions surface inside the command line ("needs your attention") and in each module. */

const { useState: uSIN, useEffect: uEIN, useRef: uRIN } = React;

function inScreen() { const m = document.querySelector(".main"); return m ? m.innerText.replace(/\n{2,}/g, "\n").slice(0, 3500) : ""; }
function inContext(ctx) {
  const base = window.buildAskContext ? window.buildAskContext(ctx) : { route: ctx.route };
  const core = window.coreModel ? window.coreModel() : { sit: [], dec: [] };
  return { ...base, openSituations: core.sit.map(s => ({ id: s.id, site: s.siteId, title: s.title, cause: s.cause, impact: s.impact })), screenText: inScreen() };
}
const IN_SYS = "You are the intelligence layer of SkyOps, a solar-PV inspection & O&M platform. You are embedded in the UI, not a chatbot. " +
  "Answer in 2–4 short sentences, decisively, using only the CONTEXT (which includes the text currently on the user's screen). " +
  "Name concrete objects in square brackets, e.g. [MIC-2026-04-033], [WO-2026-0412], [OBS-04200], [Évora Plana PV]. " +
  "End with one line starting 'Next:' that recommends a single action. Reply in the user's language. Plain text, no markdown.";

async function inAsk(q, ctx, history = []) {
  if (!window.claude || !window.claude.complete) throw new Error("AI service unavailable");
  const msgs = [...history.slice(-4).flatMap(h => [{ role: "user", content: h.q }, { role: "assistant", content: h.a || "" }]),
    { role: "user", content: IN_SYS + "\n\nCONTEXT (JSON):\n" + JSON.stringify(inContext(ctx)) + "\n\nUser: " + q }];
  return await window.claude.complete({ messages: msgs });
}

/* Local intents — instructions that act on the product directly */
const IN_ROUTES = [["portfolio", /portf[oó]lio|home|in[ií]cio/], ["sites", /\bsites?\b/], ["inspections", /inspe[cç]/], ["alerts", /alert|alarm/], ["workorders", /ordens?|work ?orders?|\bwo\b/],
  ["fleet", /frota|fleet|crew|pilot|drone/], ["field", /field|campo|t[eé]cnico/], ["warranty", /garantia|warranty/], ["commercial", /comercial|commercial|fatur|invoice|quote|or[cç]amento/],
  ["calendar", /calend/], ["zonereport", /report/], ["settings", /settings|configura/]];
function inIntent(q, ctx, nav) {
  const s = q.toLowerCase().trim();
  const mic = q.match(/MIC-\d{4}-\d{2}-\d{3}/i), wo = q.match(/WO-\d{4}-\d{4}/i);
  const site = (window.SITES || []).find(x => s.includes(x.name.toLowerCase()) || s.includes(x.name.toLowerCase().split(" ")[0]) && x.name.split(" ")[0].length > 4);
  const go = /^(abr|open|ir |go |vai|mostra|show|leva)/.test(s) || /^(abrir|ver)\b/.test(s);
  if (mic) { const m = (window.INSPECTIONS || []).find(i => i.id.toLowerCase() === mic[0].toLowerCase()); if (m) return { label: `Open ${m.id}`, run: () => { nav.setActiveSite(m.siteId); nav.setActiveMic(m.id); nav.go("workspace"); } }; }
  if (wo) return { label: `Open ${wo[0].toUpperCase()} in work orders`, run: () => nav.go("workorders") };
  if (/nova inspe|new inspection|agendar voo|schedule (a )?flight/.test(s)) return { label: "Start a new inspection" + (site ? ` at ${site.name}` : ""), run: () => window.dispatchEvent(new CustomEvent("skyops:new-insp", { detail: site ? { siteId: site.id } : {} })) };
  if (/(cria|criar|create|abre|abrir|open).*(ordem|work order|\bwo\b)/.test(s)) return { label: "Create a work order" + (site ? ` at ${site.name}` : ""), run: () => window.dispatchEvent(new CustomEvent("skyops:new-wo", { detail: { siteId: site ? site.id : ctx.activeSite } })) };
  if (/(aprova|approve).*(tud|all|todas)/.test(s)) { const open = window.coreModel().dec.filter(d => !window.coreStore.v.dec[d.id] && (!site || d.siteId === site.id)); return { label: `Approve ${open.length} open recommendation${open.length === 1 ? "" : "s"}${site ? " at " + site.name : ""}`, run: () => open.forEach(d => window.coreExecuteDec(d)) }; }
  const sev = s.match(/\b(cr[ií]tic\w*|critical|high|alt[oa]s?|medium|m[eé]di\w*|low|baix\w*)\b/);
  if (sev && /(filtr|mostra|show|only|s[oó] )/.test(s) && ctx.route === "workspace") { const map = { cri: "critical", hig: "high", alt: "high", med: "medium", méd: "medium", low: "low", bai: "low" }; const v = map[sev[1].slice(0, 3)] || "critical";
    return { label: `Filter review to ${v} detections`, run: () => { nav.setWsStage("review"); setTimeout(() => window.dispatchEvent(new CustomEvent("skyops:review-filter", { detail: { sev: v } })), 50); } }; }
  if (site && (go || s.split(" ").length <= 3)) return { label: `Open ${site.name}`, run: () => { nav.setActiveSite(site.id); nav.go("site"); } };
  if (go || s.split(" ").length <= 2) { const r = IN_ROUTES.find(([, re]) => re.test(s)); if (r) return { label: `Go to ${r[0] === "zonereport" ? "reports" : r[0] === "core" ? "Argus · autonomy" : r[0]}`, run: () => nav.go(r[0]) }; }
  return null;
}

function inSuggestions(ctx) {
  const r = ctx.route;
  if (r === "workspace" && ctx.stage === "review") return ["Show only critical", "Which detections can I accept safely?", "Create work orders for the critical ones"];
  if (r === "workspace") return ["Is this inspection on track?", "Compare with the previous cycle", "What is blocking the next stage?"];
  if (r === "site") return ["What changed since the last inspection?", "Where is this site losing the most energy?", "Create a work order here"];
  if (r === "workorders") return ["Which work orders pay back fastest?", "Who is overloaded this week?", "Create a work order"];
  if (r === "alerts") return ["Which alerts share a root cause?", "What should I acknowledge first?"];
  if (r === "commercial") return ["Which client is least profitable?", "Am I at risk of an SLA breach?"];
  if (r === "warranty") return ["Which claim is most likely to be approved?", "What evidence is missing?"];
  if (r === "fleet") return ["Which pilot can fly Zaragoza next week?", "Which drone needs attention?"];
  return ["What needs my attention today?", "Where is the portfolio losing money?", "Open Évora Plana PV"];
}

function CommandBar({ ctx, nav }) {
  const [open, setOpen] = uSIN(false);
  const [q, setQ] = uSIN("");
  const [thread, setThread] = uSIN([]);
  const [busy, setBusy] = uSIN(false);
  const inp = uRIN(null), box = uRIN(null);
  const core = window.useCoreModel ? window.useCoreModel() : { dec: [] };
  const att = core.dec.filter(d => !d.state && (ctx.route === "portfolio" || !ctx.activeSite || ["portfolio", "sites", "alerts", "workorders", "commercial", "warranty", "fleet"].includes(ctx.route) || d.siteId === ctx.activeSite)).sort((a, b) => b.impact - a.impact);
  const intent = q.trim() ? inIntent(q, ctx, nav) : null;
  uEIN(() => {
    const k = (e) => { if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); setOpen(true); setTimeout(() => inp.current && inp.current.focus(), 0); } if (e.key === "Escape") setOpen(false); };
    const ext = (e) => { setOpen(true); setQ(e.detail.q || ""); if (e.detail.run) setTimeout(() => submit(e.detail.q), 0); else setTimeout(() => inp.current && inp.current.focus(), 0); };
    const out = (e) => { if (box.current && !box.current.contains(e.target)) setOpen(false); };
    window.addEventListener("keydown", k); window.addEventListener("skyops:ask", ext); document.addEventListener("mousedown", out);
    return () => { window.removeEventListener("keydown", k); window.removeEventListener("skyops:ask", ext); document.removeEventListener("mousedown", out); };
  });
  const submit = async (text) => {
    const t = (text ?? q).trim(); if (!t) return;
    const it = inIntent(t, ctx, nav);
    if (it) { it.run(); setThread(th => [...th, { q: t, a: `Done — ${it.label.toLowerCase()}.`, act: true }]); setQ(""); return; }
    setQ(""); setOpen(false); window.agOpen && window.agOpen({ q: t, send: true }); return;
    setBusy(true);
    const entry = { q: t, a: null };
    setThread(th => [...th, entry]);
    try { const a = await inAsk(t, ctx, thread.filter(x => !x.act)); setThread(th => th.map(x => x === entry ? { ...x, a } : x)); }
    catch (e) { setThread(th => th.map(x => x === entry ? { ...x, a: "Could not reach the AI service. Commands like “open Évora”, “show only critical” or “create a work order” still work.", err: true } : x)); }
    setBusy(false);
  };
  const ctxLabel = (ctx.route === "workspace" ? `${ctx.activeMic} · ${ctx.stage}` : ["site", "siteconfig"].includes(ctx.route) ? (window.SITES || []).find(s => s.id === ctx.activeSite)?.name : null) || ({ portfolio: "Portfolio", workorders: "Work orders", alerts: "Alerts", commercial: "Commercial", warranty: "Warranty", fleet: "Fleet & crew", sites: "Sites", inspections: "Inspections", core: "SkyOps Core", field: "Field app", calendar: "Calendar", zonereport: "Reports", settings: "Settings", admin: "Admin" }[ctx.route] || ctx.route);

  return (
    <div className={`in-bar ${open ? "open" : ""}`} ref={box}>
      <div className="in-field" onClick={() => { setOpen(true); inp.current && inp.current.focus(); }}>
        <span className="in-spark"><Icon name="sparkles" size={13}/></span>
        <span className="in-ctx">{ctxLabel}</span>
        <input ref={inp} value={q} onChange={e => setQ(e.target.value)} onFocus={() => setOpen(true)} onKeyDown={e => { if (e.key === "Enter") submit(); }}
          placeholder="Ask anything or tell SkyOps what to do…"/>
        {att.length > 0 && !open && <span className="in-att"><i/>{att.length}</span>}
        <kbd>⌘K</kbd>
      </div>
      {open && <div className="in-sheet">
        {intent && <button className="in-intent" onClick={() => submit()}><Icon name="arrow_right" size={12}/><span>{intent.label}</span><kbd>↵</kbd></button>}
        {!intent && q.trim() && <button className="in-intent ag" onClick={() => submit()}><Icon name="sparkles" size={12}/><span>Ask the agent: “{q.trim()}”</span><kbd>↵</kbd></button>}
        {thread.length > 0 && <div className="in-thread">{thread.map((t, i) => (
          <div key={i} className="in-turn">
            <div className="in-q">{t.q}</div>
            <div className={`in-a ${t.err ? "err" : ""} ${t.act ? "act" : ""}`}>{t.a == null ? <span className="in-typing"><i/><i/><i/></span> : <InAnswer text={t.a} nav={nav}/>}</div>
          </div>))}
          <div className="in-thread-ft"><button className="cm-link" onClick={() => setThread([])}>Clear</button></div>
        </div>}
        {thread.length === 0 && !q && <>
          {att.length > 0 && <div className="in-sec"><div className="in-sec-h"><span className="core-mark sm"><i/>Argus</span>Needs your attention<span className="grow"/></div>
            {att.slice(0, 4).map(d => (
              <div key={d.id} className="in-dec">
                <span className={`al-sev al-sev-${d.conf >= .9 ? "low" : d.conf >= .8 ? "medium" : "high"}`} title={`${Math.round(d.conf * 100)}% confidence`}/>
                <div><b>{d.title}</b><span>{d.why}</span></div>
                {d.impact > 0 && <em className="mono">€{Math.round(d.impact).toLocaleString("en-US")}</em>}
                <button className="btn btn-primary btn-xs" onClick={() => window.coreExecuteDec(d)}>Approve</button>
              </div>))}
          </div>}
          <div className="in-sec"><div className="in-sec-h">Try</div>
            <div className="in-sugs">{inSuggestions(ctx).map(s => <button key={s} onClick={() => submit(s)}>{s}</button>)}</div></div>
          <div className="in-tip">Commands act instantly · questions and tasks go to the <button className="cm-link" onClick={() => { setOpen(false); window.agOpen(); }}>Agent panel (⌘J)</button> · hover any number or row for <b>✦</b></div>
        </>}
      </div>}
    </div>
  );
}

function InAnswer({ text, nav }) {
  const parts = text.split(/(\[[^\]]+\])/g);
  const open = (ref) => {
    const r = ref.slice(1, -1); const mic = (window.INSPECTIONS || []).find(i => i.id === r); const site = (window.SITES || []).find(s => s.name === r || s.id === r);
    if (mic) { nav.setActiveSite(mic.siteId); nav.setActiveMic(mic.id); nav.go("workspace"); }
    else if (/^WO-/.test(r)) nav.go("workorders"); else if (/^WC-/.test(r)) nav.go("warranty"); else if (/^ALT-/.test(r)) nav.go("alerts"); else if (/^(SKY|ASI)-/.test(r)) nav.go("fleet");
    else if (/^OBS-/.test(r)) { nav.setWsStage("review"); nav.go("workspace"); } else if (site) { nav.setActiveSite(site.id); nav.go("site"); }
  };
  return <>{parts.map((p, i) => p.startsWith("[") ? <button key={i} className="in-ref" onClick={() => open(p)}>{p.slice(1, -1)}</button> : p.split(/\n/).map((l, j) => /^Next:/i.test(l.trim()) ? <span key={i + "-" + j} className="in-next"><Icon name="arrow_right" size={11}/>{l.replace(/^Next:\s*/i, "")}</span> : <React.Fragment key={i + "-" + j}>{j > 0 && <br/>}{l}</React.Fragment>))}</>;
}

/* Lens: ✦ on KPIs and rows, selection → ask. One delegated layer for every module. */
function AiLens({ ctx }) {
  const [pop, setPop] = uSIN(null);
  const [hover, setHover] = uSIN(null);
  const [sel, setSel] = uSIN(null);
  const TARGETS = ".wo-kpi, .card.stat, .ws-head-meta-it, .tbl tbody tr, .core-step, .zr-kpi, .pc-kpi";
  uEIN(() => {
    const main = document.querySelector(".main"); if (!main) return;
    const mv = (e) => { const el = e.target.closest && e.target.closest(TARGETS); if (!el || !main.contains(el)) { setHover(h => h && h.el.contains(e.target) ? h : null); return; } const r = el.getBoundingClientRect(); setHover({ el, x: r.right - 22, y: r.top + 4, row: el.tagName === "TR" }); };
    const up = () => setTimeout(() => { const s = window.getSelection(); const t = s && s.toString().trim(); if (t && t.length > 2 && t.length < 400 && main.contains(s.anchorNode)) { const r = s.getRangeAt(0).getBoundingClientRect(); setSel({ t, x: r.left + r.width / 2, y: r.top - 8 }); } else setSel(null); }, 0);
    main.addEventListener("mousemove", mv); document.addEventListener("mouseup", up);
    return () => { main.removeEventListener("mousemove", mv); document.removeEventListener("mouseup", up); };
  }, [ctx.route]);
  const openPop = (el) => {
    const r = el.getBoundingClientRect(); const txt = el.innerText.replace(/\s+/g, " ").trim().slice(0, 300); const row = el.tagName === "TR";
    const head = row ? [...(el.closest("table")?.querySelectorAll("thead th") || [])].map(t => t.innerText.trim()).join(" | ") : "";
    setPop({ x: Math.min(r.left, window.innerWidth - 400), y: r.bottom + 6, txt, row, head, ans: null, mode: null }); setHover(null);
  };
  const ask = async (mode) => {
    const p = pop; const qs = { why: `Explain this ${p.row ? "row" : "metric"} and why it has this value`, todo: `What should I do about this ${p.row ? "item" : "metric"}?`, similar: "Find similar items elsewhere in the portfolio and say what they have in common" }[mode];
    setPop({ ...p, mode, ans: "…" });
    try { const a = await inAsk(`${qs}: "${p.txt}"${p.head ? ` (columns: ${p.head})` : ""}`, ctx); setPop(x => x && { ...x, ans: a }); }
    catch { setPop(x => x && { ...x, ans: "AI service unavailable.", err: true }); }
  };
  return <>
    {hover && !pop && <button className="in-lens" style={{ left: hover.x, top: hover.y }} onMouseDown={e => e.preventDefault()} onClick={(e) => { e.stopPropagation(); openPop(hover.el); }} title="Ask Argus about this"><Icon name="sparkles" size={11}/></button>}
    {sel && !pop && <button className="in-selbtn" style={{ left: sel.x, top: sel.y }} onMouseDown={e => e.preventDefault()} onClick={() => { window.agOpen({ pill: { label: "“" + sel.t.slice(0, 28) + (sel.t.length > 28 ? "…" : "") + "”", data: sel.t } }); setSel(null); }}><Icon name="sparkles" size={11}/>Ask the agent</button>}
    {pop && <div className="in-pop" style={{ left: Math.max(12, pop.x), top: Math.min(pop.y, window.innerHeight - 260) }} onMouseDown={e => e.stopPropagation()}>
      <div className="in-pop-hd"><Icon name="sparkles" size={12}/><span className="in-pop-t">{pop.txt.slice(0, 80)}{pop.txt.length > 80 ? "…" : ""}</span><button className="ask-hd-btn" onClick={() => setPop(null)}><Icon name="x" size={12}/></button></div>
      <div className="in-pop-acts">{[["why", "Why?"], ["todo", "What should I do?"], ["similar", "Find similar"]].map(([k, l]) => <button key={k} className={pop.mode === k ? "on" : ""} onClick={() => ask(k)}>{l}</button>)}</div>
      {pop.ans && <div className={`in-pop-a ${pop.err ? "err" : ""}`}>{pop.ans === "…" ? <span className="in-typing"><i/><i/><i/></span> : <InAnswer text={pop.ans} nav={window.__inNav}/>}</div>}
      {pop.ans && pop.ans !== "…" && <button className="cm-link in-pop-more" onClick={() => { window.agOpen({ pill: { label: pop.txt.slice(0, 32) + (pop.txt.length > 32 ? "…" : ""), data: pop.txt }, q: "" }); setPop(null); }}>Continue with the agent</button>}
    </div>}
  </>;
}

function IntelligenceLayer(props) { window.__inNav = props.nav; window.__inCtx = props.ctx; return <><AiLens ctx={props.ctx}/>{window.AgentPanel && <window.AgentPanel/>}</>; }
Object.assign(window, { CommandBar, IntelligenceLayer, InAnswer, inIntent });
