/* SkyOps — Work orders: detection → WO → field fix → verified by next inspection.
   Global store (localStorage) + board/list page + detail drawer + create modal. */

const { useState: uSWO, useEffect: uEWO, useMemo: uMWO } = React;

const WO_TODAY = "2026-04-17";
const WO_FLOW = ["open", "assigned", "in_progress", "done", "verified"];
const WO_LABEL = { open: "Open", assigned: "Assigned", in_progress: "In progress", done: "Done · awaiting verification", verified: "Verified" };
const WO_NEXT = { open: "Assign", assigned: "Start work", in_progress: "Mark done", done: "Verify now" };
const WO_TYPES = ["Electrical", "Module replace", "Cleaning", "Vegetation", "Tracker", "Inspection"];
const WO_TEAM_FALLBACK = ["Unassigned"];
const woTeam = () => (window.resAssignees ? window.resAssignees() : WO_TEAM_FALLBACK);
const woDrones = () => (window.resDrones ? window.resDrones() : []);

const WOS_SEED = [
  { id: "WO-2026-0412", siteId: "pt-ev-03", mic: "MIC-2026-04-033", obs: "OBS-04204", title: "Offline string — check fuses & re-energize", loc: "INV-08 · CMB-04 · STR-11", type: "Electrical", prio: "P1", status: "assigned", assignee: "R. Pardal · electrician", created: "2026-04-16", due: "2026-04-19", cost: 1200, rar: 11400, verifyMic: "MIC-2026-07-041", checklist: [["Isolate combiner", true], ["Test string fuses", false], ["Re-energize & IV trace", false]] },
  { id: "WO-2026-0413", siteId: "pt-ev-03", mic: "MIC-2026-04-033", obs: "OBS-04200", title: "Hot cell ΔT +28 °C — replace module", loc: "Zone A · A03-06", type: "Module replace", prio: "P1", status: "open", assignee: "Unassigned", created: "2026-04-16", due: "2026-04-23", cost: 2100, rar: 3900, verifyMic: "MIC-2026-07-041", checklist: [["Order spare module", false], ["Replace & torque", false], ["Thermal spot-check", false]] },
  { id: "WO-2026-0414", siteId: "pt-ev-03", mic: "MIC-2026-04-033", obs: "OBS-04201", title: "Bypass diode cluster — Zone A", loc: "Zone A · 6 modules", type: "Module replace", prio: "P2", status: "in_progress", assignee: "J. Mota · O&M crew A", created: "2026-04-16", due: "2026-04-30", cost: 6800, rar: 6200, verifyMic: "MIC-2026-07-041", checklist: [["Isolate strings", true], ["Swap junction boxes", true], ["IV trace", false]] },
  { id: "WO-2026-0415", siteId: "pt-ev-03", mic: "MIC-2026-04-033", obs: "OBS-04203", title: "Robotic wash — soiling sector C", loc: "Sector C · 1,840 modules", type: "Cleaning", prio: "P3", status: "open", assignee: "CleanTech Iberia (contractor)", created: "2026-04-16", due: "2026-05-15", cost: 2400, rar: 4100, verifyMic: "MIC-2026-07-041", checklist: [["Schedule wash window", false], ["Wash", false]] },
  { id: "WO-2026-0398", siteId: "pt-ev-03", mic: "MIC-2026-01-017", obs: "OBS-03118", title: "Vegetation clearance — NW tree line", loc: "Sector NW · 156 m²", type: "Vegetation", prio: "P3", status: "done", assignee: "S. Lima · O&M crew B", created: "2026-01-16", due: "2026-02-10", cost: 900, rar: 1800, verifyMic: "MIC-2026-04-033", checklist: [["Clear vegetation", true], ["Photo evidence", true]] },
  { id: "WO-2026-0377", siteId: "pt-ev-03", mic: "MIC-2025-10-008", obs: "OBS-02240", title: "PID — install anti-PID box CMB 4.2", loc: "CMB 4.2", type: "Electrical", prio: "P2", status: "verified", assignee: "R. Pardal · electrician", created: "2025-10-12", due: "2025-11-05", cost: 3200, rar: 5400, verifyMic: "MIC-2026-01-017", checklist: [["Install box", true], ["Commission", true]] },
  { id: "WO-2026-0420", siteId: "es-mu-02", mic: "MIC-2026-04-029", obs: "OBS-05011", title: "Hot cell cluster — inverter 3", loc: "INV-03 · 4 modules", type: "Module replace", prio: "P1", status: "assigned", assignee: "J. Mota · O&M crew A", created: "2026-04-15", due: "2026-04-16", cost: 4400, rar: 7200, verifyMic: "MIC-2026-07-044", checklist: [["Order spares", true], ["Replace", false]] },
  { id: "WO-2026-0421", siteId: "es-zr-07", mic: "MIC-2026-04-031", obs: "OBS-05402", title: "Tracker stuck — rows 14–27", loc: "Rows 14–27 · TCU-B", type: "Tracker", prio: "P1", status: "in_progress", assignee: "S. Lima · O&M crew B", created: "2026-04-18", due: "2026-04-20", cost: 1800, rar: 9600, verifyMic: "MIC-2026-07-046", checklist: [["Diagnose TCU", true], ["Replace actuator", false]] },
  { id: "WO-2026-0388", siteId: "es-ab-01", mic: "MIC-2026-01-011", obs: "OBS-02911", title: "Soiling — east blocks wash", loc: "Blocks E1–E6", type: "Cleaning", prio: "P3", status: "verified", assignee: "CleanTech Iberia (contractor)", created: "2026-01-20", due: "2026-02-15", cost: 3100, rar: 5200, verifyMic: "MIC-2026-04-028", checklist: [["Wash", true]] },
];

const woStore = {
  list: (() => { try { const s = localStorage.getItem("skyops_wos_v1"); if (s) return JSON.parse(s); } catch {} return WOS_SEED; })(),
  subs: new Set(),
  set(fn) { this.list = fn(this.list); try { localStorage.setItem("skyops_wos_v1", JSON.stringify(this.list)); } catch {} this.subs.forEach(s => s(this.list)); },
};
function woNextId(list) { const n = Math.max(421, ...(list || woStore.list).map(w => +(w.id.match(/(\d+)$/) || [0, 0])[1])); return `WO-2026-${String(n + 1).padStart(4, "0")}`; }
function useWOs() {
  const [l, setL] = uSWO(woStore.list);
  uEWO(() => { woStore.subs.add(setL); return () => woStore.subs.delete(setL); }, []);
  return l;
}
const woEur = (n) => n >= 1000 ? `€${(n / 1000).toFixed(1)}k` : `€${n}`;
const woSite = (id) => (window.SITES || []).find(s => s.id === id);
const woOverdue = (w) => w.due < WO_TODAY && (w.status === "open" || w.status === "assigned" || w.status === "in_progress");
const woInit = (n) => n.startsWith("Unassigned") ? "—" : n.split(" · ")[0].replace(/[^A-Za-z ]/g, "").split(" ").filter(Boolean).slice(0, 2).map(x => x[0]).join("").toUpperCase();

function WorkOrdersPage({ go, setActiveSite, setActiveMic, setWsStage, siteFilter }) {
  const wos = useWOs();
  const [view, setView] = uSWO("board");
  const [site, setSite] = uSWO(siteFilter || "all");
  const [prio, setPrio] = uSWO("all");
  const [q, setQ] = uSWO("");
  const [openId, setOpenId] = uSWO(null);
  const list = wos.filter(w => (site === "all" || w.siteId === site) && (prio === "all" || w.prio === prio) && (!q || (w.title + w.loc + w.id).toLowerCase().includes(q.toLowerCase())));
  const open = list.filter(w => ["open", "assigned", "in_progress"].includes(w.status));
  const k = {
    open: open.length,
    overdue: list.filter(woOverdue).length,
    awaiting: list.filter(w => w.status === "done").length,
    protected: list.filter(w => w.status === "verified" || w.status === "done").reduce((a, w) => a + w.rar, 0),
    atRisk: open.reduce((a, w) => a + w.rar, 0),
  };
  const cur = wos.find(w => w.id === openId);

  return (
    <div className={siteFilter ? "wo wo-embedded" : "page wo"}>
      {!siteFilter && <div className="page-head">
        <div className="title">
          <div className="kicker">Operate · close the loop</div>
          <h1>Work orders</h1>
          <div className="sub">Every fix starts from a detection and is closed when the next inspection confirms it.</div>
        </div>
        <div className="actions"><button className="btn btn-primary" onClick={() => window.dispatchEvent(new CustomEvent("skyops:new-wo", { detail: {} }))}><Icon name="plus" size={12}/>New work order</button></div>
      </div>}

      <div className="wo-kpis">
        <div className="wo-kpi"><span className="caps">Open</span><b className="mono">{k.open}</b><em>{woEur(k.atRisk)}/yr at risk</em></div>
        <div className={`wo-kpi ${k.overdue > 0 ? "is-crit" : ""}`}><span className="caps">Overdue</span><b className="mono">{k.overdue}</b><em>past due date</em></div>
        <div className="wo-kpi"><span className="caps">Awaiting verification</span><b className="mono">{k.awaiting}</b><em>closed by next inspection</em></div>
        <div className="wo-kpi is-ok"><span className="caps">Revenue protected</span><b className="mono">{woEur(k.protected)}/yr</b><em>done + verified</em></div>
      </div>

      {window.CoreStrip && <window.CoreStrip dom="maintenance" siteId={siteFilter || undefined} title="Argus · work to create or re-prioritise"/>}
      <div className="wo-tb">
        <div className="ps-seg">{[["board","Board"],["list","List"]].map(([v,l]) => <button key={v} className={view === v ? "on" : ""} onClick={() => setView(v)}>{l}</button>)}</div>
        {!siteFilter && <select className="sel wo-sel" value={site} onChange={e => setSite(e.target.value)}>
          <option value="all">All sites</option>
          {(window.SITES || []).map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
        </select>}
        <div className="ps-seg">{["all","P1","P2","P3"].map(p => <button key={p} className={prio === p ? "on" : ""} onClick={() => setPrio(p)}>{p === "all" ? "All priorities" : p}</button>)}</div>
        <div className="lg-search wo-search"><Icon name="search" size={11}/><input value={q} onChange={e => setQ(e.target.value)} placeholder="Search work orders"/></div>
        {siteFilter && <><span className="grow"/><button className="btn btn-primary btn-xs" onClick={() => window.dispatchEvent(new CustomEvent("skyops:new-wo", { detail: { siteId: siteFilter } }))}><Icon name="plus" size={11}/>New work order</button></>}
      </div>

      {view === "board" ? (
        <div className="wo-board">
          {WO_FLOW.map(st => {
            const col = list.filter(w => w.status === st);
            return (
              <div key={st} className="wo-col">
                <div className="wo-col-h"><span className={`wo-st wo-st-${st}`}/>{WO_LABEL[st].split(" · ")[0]}<em className="mono">{col.length}</em></div>
                {col.map(w => <WoCard key={w.id} w={w} onOpen={() => setOpenId(w.id)}/>)}
                {col.length === 0 && <div className="wo-col-empty">—</div>}
              </div>
            );
          })}
        </div>
      ) : (
        <div className="card">
          <table className="tbl">
            <thead><tr><th>WO</th><th>Prio</th><th>Title</th><th>Site · location</th><th>Status</th><th>Assignee</th><th>Due</th><th className="r">€ at risk/yr</th></tr></thead>
            <tbody>{list.map(w => (
              <tr key={w.id} onClick={() => setOpenId(w.id)}>
                <td className="mono">{w.id}</td>
                <td><span className={`wo-prio wo-prio-${w.prio}`}>{w.prio}</span></td>
                <td>{w.title}</td>
                <td className="sec">{woSite(w.siteId)?.name} · <span className="mono">{w.loc}</span></td>
                <td><span className="wo-stl"><span className={`wo-st wo-st-${w.status}`}/>{WO_LABEL[w.status].split(" · ")[0]}</span></td>
                <td className="sec">{w.assignee.split(" · ")[0]}</td>
                <td className="mono" style={{ color: woOverdue(w) ? "var(--sev-critical)" : undefined }}>{w.due}</td>
                <td className="r mono">{woEur(w.rar)}</td>
              </tr>
            ))}</tbody>
          </table>
        </div>
      )}

      {cur && <WoDrawer w={cur} onClose={() => setOpenId(null)} go={go} setActiveSite={setActiveSite} setActiveMic={setActiveMic} setWsStage={setWsStage}/>}
    </div>
  );
}

function WoCard({ w, onOpen }) {
  return (
    <button className={`wo-card ${woOverdue(w) ? "is-late" : ""}`} onClick={onOpen}>
      <div className="wo-card-hd"><span className={`wo-prio wo-prio-${w.prio}`}>{w.prio}</span><span className="mono wo-id">{w.id}</span><span className="wo-type">{w.type}</span></div>
      <div className="wo-card-t">{w.title}</div>
      <div className="wo-card-l mono">{woSite(w.siteId)?.name} · {w.loc}</div>
      <div className="wo-card-ft">
        <span className="wo-av" title={w.assignee}>{woInit(w.assignee)}</span>
        {w.drone && <span className="mono wo-drone" title={w.drone}><Icon name="drone" size={9}/>{w.drone.split(" · ")[0]}</span>}
        <span className={`mono wo-due ${woOverdue(w) ? "late" : ""}`}>{woOverdue(w) ? "overdue " : "due "}{w.due.slice(5)}</span>
        <span className="mono wo-rar">{woEur(w.rar)}/yr</span>
      </div>
      {w.status === "done" && <div className="wo-verify"><Icon name="clock" size={10}/>Verify in {w.verifyMic}</div>}
    </button>
  );
}

function WoDrawer({ w, onClose, go, setActiveSite, setActiveMic, setWsStage }) {
  const upd = (patch) => woStore.set(l => l.map(x => x.id === w.id ? { ...x, ...patch } : x));
  const idx = WO_FLOW.indexOf(w.status);
  const advance = () => { const n = WO_FLOW[idx + 1]; if (!n) return; upd({ status: n, ...(n === "assigned" && w.assignee.startsWith("Unassigned") ? { assignee: woTeam()[0] } : {}) }); };
  const openDetection = () => { setActiveSite(w.siteId); setActiveMic(w.mic); setWsStage("review"); go("workspace"); };
  const lineage = [
    ["Detected", `${w.obs} · ${w.mic}`, true],
    ["WO created", w.created, true],
    ["Assigned", w.assignee.split(" · ")[0], idx >= 1],
    ["Field fix", idx >= 3 ? "done" : idx === 2 ? "in progress" : "pending", idx >= 3],
    ["Verified", idx >= 4 ? `in ${w.verifyMic}` : `by ${w.verifyMic}`, idx >= 4],
  ];
  return (
    <>
      <div className="wo-scrim" onClick={onClose}/>
      <aside className="wo-drawer" role="dialog" aria-label={w.id}>
        <div className="wo-dr-hd">
          <div>
            <div className="mono wo-dr-id">{w.id} · <span className={`wo-prio wo-prio-${w.prio}`}>{w.prio}</span></div>
            <div className="wo-dr-t">{w.title}</div>
            <div className="sec wo-dr-s">{woSite(w.siteId)?.name} · <span className="mono">{w.loc}</span></div>
          </div>
          <button className="ask-hd-btn" onClick={onClose}><Icon name="x" size={13}/></button>
        </div>
        <div className="wo-dr-body">
          <div className="wo-lin">
            {lineage.map(([l, s, ok], i) => (
              <div key={l} className={`wo-lin-it ${ok ? "ok" : ""} ${i === Math.min(idx + 1, 4) && !ok ? "cur" : ""}`}>
                <span className="wo-lin-dot">{ok ? <Icon name="check" size={9}/> : i + 1}</span>
                <span className="wo-lin-l">{l}</span><span className="mono wo-lin-s">{s}</span>
              </div>
            ))}
          </div>
          <div className="wo-dr-grid">
            <label className="field"><span className="caps">Status</span><select className="sel" value={w.status} onChange={e => upd({ status: e.target.value })}>{WO_FLOW.map(s => <option key={s} value={s}>{WO_LABEL[s]}</option>)}</select></label>
            <label className="field"><span className="caps">Priority</span><select className="sel" value={w.prio} onChange={e => upd({ prio: e.target.value })}>{["P1","P2","P3"].map(p => <option key={p}>{p}</option>)}</select></label>
            <label className="field"><span className="caps">Assignee</span><select className="sel" value={w.assignee} onChange={e => upd({ assignee: e.target.value })}>{woTeam().map(t => <option key={t}>{t}</option>)}</select></label>
            <label className="field"><span className="caps">Due</span><input className="inp" type="date" value={w.due} onChange={e => upd({ due: e.target.value })}/></label>
            <label className="field" style={{ gridColumn: "1 / -1" }}><span className="caps">Drone (re-fly / verification)</span><select className="sel" value={w.drone || ""} onChange={e => upd({ drone: e.target.value })}><option value="">None</option>{woDrones().map(d => <option key={d.id} value={window.droneLabel(d)}>{window.droneLabel(d)} · {d.status}</option>)}</select></label>
          </div>
          {window.resByLabel && window.resByLabel(w.assignee) && (() => { const r = window.resByLabel(w.assignee); return <div className="fl-asg"><window.ResKind k={r.kind}/><span>{r.kind === "company" ? r.service + " · " + r.contract : r.org + " · " + r.region}</span></div>; })()}
          <div className="wo-dr-money">
            <div><span className="caps">Est. cost</span><b className="mono">{woEur(w.cost)}</b></div>
            <div><span className="caps">Revenue protected</span><b className="mono" style={{ color: "var(--sev-low)" }}>{woEur(w.rar)}/yr</b></div>
            <div><span className="caps">Payback</span><b className="mono">{(w.cost / w.rar * 12).toFixed(1)} mo</b></div>
          </div>
          {w.fieldReport && <div className="wo-dr-sec"><div className="caps">Field report{w.fieldReport.completedAt ? " · " + w.fieldReport.completedAt : ""}</div>
            {[["Photos", [w.fieldReport.photos?.before && "before " + w.fieldReport.photos.before, w.fieldReport.photos?.after && "after " + w.fieldReport.photos.after].filter(Boolean).join(" · ") || "—"],
              w.fieldReport.part && ["Module swap", `${w.fieldReport.part.out} → ${w.fieldReport.part.in}`], w.fieldReport.measures && ["Measurements", `Voc ${w.fieldReport.measures.voc || "—"} V · Isc ${w.fieldReport.measures.isc || "—"} A · ${w.fieldReport.measures.ins || "—"} MΩ`],
              w.fieldReport.note && ["Note", w.fieldReport.note], ["Signed", w.fieldReport.signedBy || "—"]].filter(Boolean).map(([k, v]) => <div key={k} className="ps-kv"><span>{k}</span><b>{v}</b></div>)}
          </div>}
          <div className="wo-dr-sec">
            <div className="caps">Checklist</div>
            {w.checklist.map(([t, d], i) => (
              <label key={i} className="wo-chk"><input type="checkbox" checked={d} onChange={() => upd({ checklist: w.checklist.map((c, j) => j === i ? [c[0], !c[1]] : c) })}/><span className={d ? "done" : ""}>{t}</span></label>
            ))}
          </div>
          <div className="wo-dr-sec">
            <div className="caps">Source</div>
            <button className="wo-src" onClick={openDetection}><Icon name="eye" size={12}/><span><b className="mono">{w.obs}</b> in <span className="mono">{w.mic}</span></span><Icon name="arrow_right" size={11}/></button>
          </div>
        </div>
        <div className="wo-dr-ft">
          <button className="btn btn-ghost btn-xs" onClick={() => { setActiveSite(w.siteId); go("site"); }}>Open site</button>
          <span className="grow"/>
          {WO_NEXT[w.status] && <button className="btn btn-primary btn-xs" onClick={advance}><Icon name="arrow_right" size={11}/>{WO_NEXT[w.status]}</button>}
        </div>
      </aside>
    </>
  );
}

function WoCreateModal({ prefill, onClose }) {
  const [f, setF] = uSWO(() => ({
    title: prefill.title || "", siteId: prefill.siteId || (window.SITES || [])[0]?.id, loc: prefill.loc || "",
    type: prefill.type || "Electrical", prio: prefill.prio || "P2", assignee: prefill.assignee || "Unassigned", due: "2026-04-30",
    drone: prefill.drone || "", mic: prefill.mic || "", obs: prefill.obs || "—", rar: prefill.rar || 2000, cost: prefill.cost || 1500,
  }));
  const set = (k) => (e) => setF(x => ({ ...x, [k]: e.target.value }));
  const create = () => {
    const n = 422 + woStore.list.length;
    const insp = (window.INSPECTIONS || []).filter(i => i.siteId === f.siteId && (i.status === "scheduled" || i.status === "draft"));
    const wo = { id: woNextId(), ...f, rar: +f.rar, cost: +f.cost, status: f.assignee.startsWith("Unassigned") ? "open" : "assigned", created: WO_TODAY, verifyMic: insp[0]?.id || "next inspection", checklist: [["Diagnose on site", false], ["Fix", false], ["Photo evidence", false]] };
    woStore.set(l => [wo, ...l]);
    onClose(wo);
  };
  return (
    <div className="ni-scrim" onClick={() => onClose()}>
      <div className="ni-modal" onClick={e => e.stopPropagation()} role="dialog" aria-label="New work order">
        <div className="ni-hd"><div><div className="kicker">Work order</div><h3>New work order</h3></div><button className="ask-hd-btn" onClick={() => onClose()}><Icon name="x" size={13}/></button></div>
        {prefill.obs && <div className="ni-from"><Icon name="link" size={11}/>From detection <b className="mono">{prefill.obs}</b> · <span className="mono">{prefill.mic}</span></div>}
        <div className="ni-body ni-grid">
          <label className="field ni-span"><span>Title</span><input className="inp" value={f.title} onChange={set("title")} placeholder="What needs to be fixed"/></label>
          <label className="field"><span>Site</span><select className="sel" value={f.siteId} onChange={set("siteId")}>{(window.SITES || []).map(s => <option key={s.id} value={s.id}>{s.name}</option>)}</select></label>
          <label className="field"><span>Location</span><input className="inp mono" value={f.loc} onChange={set("loc")} placeholder="String, zone or module"/></label>
          <label className="field"><span>Type</span><select className="sel" value={f.type} onChange={set("type")}>{WO_TYPES.map(t => <option key={t}>{t}</option>)}</select></label>
          <label className="field"><span>Priority</span><select className="sel" value={f.prio} onChange={set("prio")}>{["P1","P2","P3"].map(p => <option key={p}>{p}</option>)}</select></label>
          <label className="field"><span>Assignee</span><select className="sel" value={f.assignee} onChange={set("assignee")}>{woTeam().map(t => <option key={t}>{t}</option>)}</select></label>
          <label className="field"><span>Drone</span><select className="sel" value={f.drone} onChange={set("drone")}><option value="">None</option>{woDrones().map(d => <option key={d.id} value={window.droneLabel(d)}>{d.id} · {d.model} · {d.status}</option>)}</select></label>
          <label className="field"><span>Due</span><input className="inp" type="date" value={f.due} onChange={set("due")}/></label>
          <label className="field"><span>Est. cost (€)</span><input className="inp mono" type="number" value={f.cost} onChange={set("cost")}/></label>
          <label className="field"><span>Revenue at risk (€/yr)</span><input className="inp mono" type="number" value={f.rar} onChange={set("rar")}/></label>
        </div>
        <div className="ni-ft"><span className="sec ni-note">Closed automatically when the next inspection confirms the fix.</span><span className="grow"/><button className="btn btn-ghost" onClick={() => onClose()}>Cancel</button><button className="btn btn-primary" disabled={!f.title.trim()} onClick={create}><Icon name="check" size={12}/>Create work order</button></div>
      </div>
    </div>
  );
}

Object.assign(window, { WorkOrdersPage, WoCreateModal, woStore, useWOs, woNextId });
