// ─────────────────────────────────────────────────────────────────────────────
// Operator Tablet — app shell. Renders the scaled 1280×800 stage, the tablet
// top app bar (C-102), optional offline banner, the current page, an optional
// bottom tab bar, and the Tweaks panel. Per-screen HTML sets window.OPT_START.
// Pages register on window.OptPages[route] = { chrome, title, sub, tab, render }.
// Loads LAST. Reuses hooks from op-ui.jsx.
// ─────────────────────────────────────────────────────────────────────────────

const SIc = window.Icons;
const OD = window.OD;

// route → { code, label, href, group }
const PAGE_NAV = [
  ["dashboard",    "OPT-GATE-01", "Gate dashboard",            "OPT-GATE-01.html", "Gate"],
  ["scan",         "OPT-GATE-02", "Scan QR / gate pass",       "OPT-GATE-02.html", "Entry flow"],
  ["scanMatch",    "OPT-GATE-03", "Scan result — matched",     "OPT-GATE-03.html", "Entry flow"],
  ["scanMismatch", "OPT-GATE-04", "Scan result — mismatch",    "OPT-GATE-04.html", "Entry flow"],
  ["manualEntry",  "OPT-GATE-05", "Manual gate entry",         "OPT-GATE-05.html", "Entry flow"],
  ["captureDriver","OPT-GATE-06", "Capture driver & truck",    "OPT-GATE-06.html", "Entry flow"],
  ["verify",       "OPT-GATE-07", "Verification checklist",    "OPT-GATE-07.html", "Entry flow"],
  ["generatePass", "OPT-GATE-08", "Generate gate pass",        "OPT-GATE-08.html", "Entry flow"],
  ["weighGross",   "OPT-GATE-09", "Weighbridge — gross",       "OPT-GATE-09.html", "Weighbridge"],
  ["weighTare",    "OPT-GATE-10", "Weighbridge — tare",        "OPT-GATE-10.html", "Weighbridge"],
  ["slipViewer",   "OPT-GATE-11", "Weight slip viewer",        "OPT-GATE-11.html", "Weighbridge"],
  ["exitVerify",   "OPT-GATE-12", "Gate exit — verify",        "OPT-GATE-12.html", "Exit flow"],
  ["exitLog",      "OPT-GATE-13", "Gate exit — log",           "OPT-GATE-13.html", "Exit flow"],
  ["activeTrucks", "OPT-GATE-14", "Active trucks on site",     "OPT-GATE-14.html", "Monitor"],
  ["movementLog",  "OPT-GATE-15", "Truck movement log",        "OPT-GATE-15.html", "Monitor"],
  ["exceptions",   "OPT-GATE-16", "Audit / exceptions",        "OPT-GATE-16.html", "Monitor"],
  ["emptyState",   "OPT-GATE-17", "Empty — no arrivals",       "OPT-GATE-17.html", "Gate"],
  ["cameraError",  "OPT-GATE-18", "Camera permission error",   "OPT-GATE-18.html", "Entry flow"],
];
const HREF = Object.fromEntries(PAGE_NAV.map(([r, , , h]) => [r, h]));

// Bottom tabs
const TABS = [
  { key: "Gate",       route: "dashboard",    icon: SIc.Gate },
  { key: "Active",     route: "activeTrucks", icon: SIc.Truck, badge: 5 },
  { key: "Exceptions", route: "exceptions",   icon: SIc.Warning, badge: 4 },
];

// Per-screen state tweaks (rendered for the active route only)
const STATE_TWEAKS = {
  dashboard:    { label: "Dashboard (OPT-01)", opts: [["default","Default — active day"],["quiet","Quiet — none on site"],["noExpected","No scheduled arrivals"],["loading","Loading"],["offline","Offline"]] },
  scan:         { label: "Scanner (OPT-02)", opts: [["scanning","Scanning"],["poorFocus","Poor focus / glare hint"],["offline","Offline (cached lookup)"]] },
  scanMatch:    { label: "Matched (OPT-03)", opts: [["ontime","On-time match"],["early","Early arrival"],["late","Late arrival"],["grace","Outside grace (override)"],["already","Already arrived"]] },
  scanMismatch: { label: "Mismatch (OPT-04)", opts: [["generic","Generic mismatch"],["window","Out of window"],["facility","Wrong facility"],["closed","Already closed"]] },
  manualEntry:  { label: "Manual entry (OPT-05)", opts: [["empty","Empty form"],["matched","Order matched"],["noOrder","No open orders"],["errors","Validation errors"],["outbound","Outbound dispatch"]] },
  captureDriver:{ label: "Capture (OPT-06)", opts: [["empty","All empty"],["partial","Partial"],["filled","All filled"],["storageLow","Storage low"]] },
  verify:       { label: "Verify (OPT-07)", opts: [["pending","Awaiting checks"],["allMatch","All match"],["mismatch","Mismatch detected"]] },
  generatePass: { label: "Gate pass (OPT-08)", opts: [["success","Default success"],["noPrinter","Printer offline"],["noPhone","No driver phone"]] },
  weighGross:   { label: "Gross (OPT-09)", opts: [["empty","Empty"],["noPhoto","Weight, no photo"],["allSet","All set"],["variance","Variance warning"],["outlier","Outlier warning"]] },
  weighTare:    { label: "Tare (OPT-10)", opts: [["within","Within tolerance"],["over","Over-delivery"],["under","Under-delivery"],["negative","Negative (invalid)"],["empty","Empty"]] },
  slipViewer:   { label: "Slip viewer (OPT-11)", opts: [["single","Single slip"],["multiple","Multiple slips"],["disputed","Disputed"]] },
  exitVerify:   { label: "Exit verify (OPT-12)", opts: [["allClear","All clear"],["pending","Pending clearances"],["exited","Already exited"]] },
  exitLog:      { label: "Exit log (OPT-13)", opts: [["default","Default"],["printerOffline","Printer offline"],["longDwell","Long dwell"]] },
  activeTrucks: { label: "Active trucks (OPT-14)", opts: [["default","Default"],["empty","Empty"],["noResults","Filtered — no results"],["longDwell","Long-dwell alert"]] },
  movementLog:  { label: "Movement log (OPT-15)", opts: [["inProgress","In progress"],["completed","Completed"],["disputes","With disputes"],["loading","Loading"]] },
  exceptions:   { label: "Exceptions (OPT-16)", opts: [["default","With exceptions"],["urgent","Critical unresolved"],["empty","Empty"]] },
  emptyState:   { label: "Empty state (OPT-17)", opts: [["quiet","Quiet day"],["firstRun","First-run / welcome"]] },
  cameraError:  { label: "Camera error (OPT-18)", opts: [["permission","Permission denied"],["busy","Hardware busy"],["fault","Hardware fault"]] },
};

const TWEAKS_DEFAULTS = /*EDITMODE-BEGIN*/{
  "dark": false,
  "bgPattern": "two",
  "offline": false,
  "dashboard": "default",
  "scan": "scanning",
  "scanMatch": "ontime",
  "scanMismatch": "generic",
  "manualEntry": "empty",
  "captureDriver": "filled",
  "verify": "pending",
  "entrySrc": "app",
  "generatePass": "success",
  "weighGross": "empty",
  "weighTare": "within",
  "slipViewer": "single",
  "exitVerify": "allClear",
  "exitLog": "default",
  "activeTrucks": "default",
  "movementLog": "completed",
  "exceptions": "default",
  "emptyState": "quiet",
  "cameraError": "permission"
}/*EDITMODE-END*/;

// ── Top app bar ──
const AppBar = ({ page, offline, onToggleDark, dark, go, route }) => {
  const flow = page.chrome === "flow";
  return (
    <header className="op-appbar">
      {flow ? (
        <>
          <button className="op-ab-back" aria-label="Back" onClick={() => (page.back ? go(page.back) : history.back())}><SIc.ChevronLeft size={24}/></button>
          <div style={{ minWidth: 0 }}>
            <div className="op-ab-title">{page.title}</div>
            {page.sub && <div className="op-ab-sub">{page.sub}</div>}
          </div>
        </>
      ) : (
        <div className="op-ab-brand">
          <span className="op-ab-mark"><SIc.Leaf size={19}/></span>
          <div style={{ minWidth: 0 }}>
            <div className="op-ab-facility">{OD.FACILITY.name}</div>
            <div className="op-ab-gate"><SIc.MapPin size={11}/> {OD.FACILITY.plant} · {OD.FACILITY.gate}</div>
          </div>
        </div>
      )}
      <div className="op-ab-spacer"/>
      <div className="op-ab-right">
        <span className={`op-sync ${offline ? "offline" : ""}`} title="Network & sync">
          <span className="op-sync-dot"/>
          {offline ? <><SIc.WifiOff size={14}/> Offline</> : <><SIc.Wifi size={14}/> Synced</>}
        </span>
        <span className="op-ab-clock">09:16</span>
        <button className="op-iconbtn ghost" aria-label="Toggle theme" onClick={onToggleDark}>{dark ? <SIc.Sun size={18}/> : <SIc.Moon size={18}/>}</button>
        <button className="op-iconbtn ghost" aria-label="Notifications"><SIc.Bell size={18}/><span className="op-dot"/></button>
        <div className="op-ab-user">
          <span className="avatar avatar-avocado">{OD.OPERATOR.initials}</span>
          <div>
            <div className="op-au-name">{OD.OPERATOR.name}</div>
            <div className="op-au-role">{OD.OPERATOR.role}</div>
          </div>
        </div>
      </div>
    </header>
  );
};

// ── Root ──
const OperatorApp = () => {
  const route = window.OPT_START || "dashboard";
  const [scale, setScale] = useState(1);
  const [t, setTweak] = window.useTweaks ? window.useTweaks(TWEAKS_DEFAULTS) : [TWEAKS_DEFAULTS, () => {}];

  // page-level offline can come from the global toggle OR a per-screen offline state
  const offline = !!t.offline || t[route] === "offline";

  useEffect(() => { document.documentElement.classList.toggle("dark", !!t.dark); }, [t.dark]);
  useEffect(() => { document.documentElement.setAttribute("data-pattern", t.bgPattern || "two"); }, [t.bgPattern]);

  useEffect(() => {
    const fit = () => {
      const pad = 24;
      setScale(Math.min((window.innerWidth - pad) / 1332, (window.innerHeight - pad) / 852, 1));
    };
    fit();
    window.addEventListener("resize", fit);
    return () => window.removeEventListener("resize", fit);
  }, []);

  const go = useCallback((r) => { if (HREF[r]) window.location.href = HREF[r]; }, []);
  const page = window.OptPages?.[route];
  const chrome = page?.chrome || "tabs";
  const showTabs = chrome === "tabs";
  const showAppbar = chrome !== "bare";

  const ctx = { t, setTweak, go, offline, route };
  const st = STATE_TWEAKS[route];

  return (
    <div className="op-stage">
      <div className="op-scaler" style={{ transform: `scale(${scale})` }}>
        <div className="op-device">
          <span className="op-cam"/>
          <div className="op-screen">
          <div className="op-osbar">
            <span className="op-os-time">09:16</span>
            <span className="op-os-right">
              <SIc.Signal size={15}/>
              {offline ? <SIc.WifiOff size={15}/> : <SIc.Wifi size={15}/>}
              <span className="op-os-batt">100%</span>
              <SIc.Battery size={20}/>
            </span>
          </div>
          {showAppbar && <AppBar page={page} offline={offline} dark={!!t.dark} onToggleDark={() => setTweak("dark", !t.dark)} go={go} route={route}/>}
          {showAppbar && offline && (
            <div className="op-offline-bar">
              <SIc.WifiOff size={15}/>
              <span>Offline — actions will queue and sync when the connection returns. Cached orders valid for 48h.</span>
              <SIc.ChevronRight size={15} className="op-ob-chev"/>
            </div>
          )}
          {page
            ? page.render(ctx)
            : <div className="op-empty"><div className="op-empty-title">Screen not found</div></div>}
          {showTabs && (
            <div className="op-tabbar-wrap">
              <nav className="op-tabbar">
                {TABS.map(tab => {
                  const on = tab.key === (page.tab || "Gate");
                  return (
                    <button key={tab.key} className={`op-tab ${on ? "on" : ""}`} onClick={() => go(tab.route)}>
                      {tab.badge != null && <span className="op-tab-badge">{tab.badge}</span>}
                      <tab.icon size={22}/>
                      <span className="op-tab-label">{tab.key}</span>
                    </button>
                  );
                })}
              </nav>
            </div>
          )}
        </div>
        </div>
      </div>

      {window.TweaksPanel && (
        <window.TweaksPanel title="Tweaks">
          <window.TweakSection label="Appearance">
            <window.TweakToggle label="Dark mode" value={t.dark} onChange={(v) => setTweak("dark", v)}/>
            <window.TweakRadio label="Background pattern" value={t.bgPattern} onChange={(v) => setTweak("bgPattern", v)}
              options={[{ value: "two", label: "Fields" }, { value: "none", label: "None" }]}/>
            <window.TweakToggle label="Offline mode" value={t.offline} onChange={(v) => setTweak("offline", v)}/>
          </window.TweakSection>
          <window.TweakSection label="Go to screen">
            <window.TweakSelect label="Screen" value={route}
              onChange={(v) => go(v)}
              options={PAGE_NAV.map(([r, code, label]) => ({ value: r, label: `${code} · ${label}` }))}/>
          </window.TweakSection>
          {st && (
            <window.TweakSection label={st.label}>
              <window.TweakSelect label="Screen state" value={t[route]} onChange={(v) => setTweak(route, v)}
                options={st.opts.map(([value, label]) => ({ value, label }))}/>
            </window.TweakSection>
          )}
          {(route === "verify" || route === "generatePass") && (
            <window.TweakSection label="Entry source">
              <window.TweakSelect label="GNP origin" value={t.entrySrc || "app"} onChange={(v) => setTweak("entrySrc", v)}
                options={[{ value: "app", label: "Farmer app pass" }, { value: "manual", label: "Manual entry (gate-generated)" }]}/>
            </window.TweakSection>
          )}
        </window.TweaksPanel>
      )}
    </div>
  );
};

const opRoot = ReactDOM.createRoot(document.getElementById("root"));
opRoot.render(<OperatorApp/>);
