// ─────────────────────────────────────────────────────────────────────────────
// Operator Tablet — shared UI primitives. Declares React hooks ONCE (global,
// reused by pages + shell). Exports reusable components on window.Op.
// Loaded after icons + data, before pages + shell.
// ─────────────────────────────────────────────────────────────────────────────

const { useState, useEffect, useRef, useMemo, useCallback } = React;
const OpIc = window.Icons;

// ── Button ──
const Btn = ({ variant = "primary", size, icon: Icon, iconRight, loading, block, children, ...rest }) => (
  <button {...rest}
    className={`op-btn op-btn-${variant} ${size ? "op-btn-" + size : ""} ${block ? "op-btn-block" : ""} ${rest.className || ""}`}
    disabled={rest.disabled || loading}>
    {loading ? <span className="op-spin"/> : (Icon ? <Icon size={size === "hero" ? 22 : 18}/> : null)}
    {children}
    {iconRight && !loading ? React.createElement(iconRight, { size: 18 }) : null}
  </button>
);

// ── Status pill (reuses AMOMS badge tokens) ──
const Pill = ({ tone = "closed", children, dot }) => (
  <span className={`badge badge-${tone}`}>{dot && <span className="dot" style={{ background: "currentColor" }}/>}{children}</span>
);

// ── Severity tag (C-015) ──
const SEV = { low: ["sev-low", "Low"], medium: ["sev-medium", "Medium"], high: ["sev-high", "High"], critical: ["sev-critical", "Critical"] };
const Severity = ({ level }) => { const [c, l] = SEV[level] || SEV.low; return <span className={`badge badge-${c}`}>{l}</span>; };

// ── Banner (C-106) ──
const Banner = ({ tone = "neutral", icon: Icon, title, desc, children, style }) => (
  <div className={`op-banner op-banner-${tone}`} style={style}>
    {Icon && <span className="op-banner-ic"><Icon size={19}/></span>}
    <div style={{ flex: 1, minWidth: 0 }}>
      {title && <div className="op-banner-title">{title}</div>}
      {desc && <div className="op-banner-desc">{desc}</div>}
      {children}
    </div>
  </div>
);

// ── Status strip (full-width header on result screens) ──
const Strip = ({ tone = "success", icon: Icon, title, sub }) => (
  <div className={`op-strip ${tone}`}>
    {Icon && <span className="op-strip-ic"><Icon size={22}/></span>}
    <div>
      <div className="op-strip-title">{title}</div>
      {sub && <div className="op-strip-sub">{sub}</div>}
    </div>
  </div>
);

// ── KPI tile (C-110) ──
const Kpi = ({ label, icon: Icon, value, unit, warn, onClick }) => (
  <div className={`op-card op-kpi ${warn ? "warn" : ""} ${onClick ? "clickable" : ""}`} onClick={onClick}>
    <span className="op-kpi-label">{Icon && <Icon size={14}/>}{label}</span>
    <span className="op-kpi-value">{value}{unit && <small>{unit}</small>}</span>
  </div>
);

// ── Toggle switch row (anti-fraud confirm) ──
const ToggleRow = ({ on, onChange, title, sub, icon: Icon }) => (
  <button className={`op-toggle-row ${on ? "on" : ""}`} onClick={() => onChange(!on)} style={{ width: "100%", textAlign: "left" }}>
    {Icon && <span className="op-row-thumb" style={{ width: 44, height: 44 }}><Icon size={20}/></span>}
    <div className="op-tr-body">
      <div className="op-tr-title">{title}</div>
      {sub && <div className="op-tr-sub">{sub}</div>}
    </div>
    <span className={`op-switch ${on ? "on" : ""}`}/>
  </button>
);

// ── Large number / weight input (C-004 / C-118) ──
const NumInput = ({ value, onChange, step = 10, suffix = "kg", placeholder = "0" }) => {
  const set = (v) => onChange(Math.max(0, v));
  return (
    <div className="op-num">
      <button className="op-num-btn" onClick={() => set((value || 0) - step)} aria-label="Decrease">−</button>
      <input className="op-num-input" inputMode="numeric" value={value ? value.toLocaleString("en-KE") : ""}
        placeholder={placeholder}
        onChange={(e) => { const n = parseInt(e.target.value.replace(/\D/g, ""), 10); set(isNaN(n) ? 0 : n); }}/>
      <span className="op-num-suffix">{suffix}</span>
      <button className="op-num-btn" style={{ borderLeft: "1px solid var(--border)" }} onClick={() => set((value || 0) + step)} aria-label="Increase">+</button>
    </div>
  );
};

// ── Photo capture tile (C-011) ──
const PhotoTile = ({ filled, label, hint, tag, onTap, aspect = "1 / 1", required }) => (
  <button className={`op-phototile ${filled ? "filled" : ""}`} onClick={onTap} style={{ aspectRatio: aspect, width: "100%" }}>
    {filled ? (
      <>
        <span className="op-pt-img"/>
        <span className="op-pt-check"><OpIc.Check size={17}/></span>
        {tag && <span className="op-pt-tag">{tag}</span>}
        <span className="op-pt-retake"><OpIc.Camera size={13}/> Re-take</span>
      </>
    ) : (
      <>
        <OpIc.Camera size={30}/>
        <div className="op-pt-label">{label}{required && <span style={{ color: "var(--soil)" }}> *</span>}</div>
        {hint && <div className="op-pt-hint">{hint}</div>}
      </>
    )}
  </button>
);

// ── Deterministic QR-ish block (C-116) — faithful placeholder, not scannable ──
const QR = ({ value = "GPN", size = 220 }) => {
  const n = 27;
  const cells = useMemo(() => {
    let h = 2166136261;
    for (let i = 0; i < value.length; i++) { h ^= value.charCodeAt(i); h = Math.imul(h, 16777619); }
    const rng = () => { h ^= h << 13; h ^= h >>> 17; h ^= h << 5; return (h >>> 0) / 4294967296; };
    const g = Array.from({ length: n }, () => Array.from({ length: n }, () => rng() > 0.52));
    const finder = (r, c) => {
      for (let i = -1; i <= 7; i++) for (let j = -1; j <= 7; j++) {
        const rr = r + i, cc = c + j; if (rr < 0 || cc < 0 || rr >= n || cc >= n) continue;
        if (i >= 0 && i <= 6 && j >= 0 && j <= 6) {
          const border = (i === 0 || i === 6) || (j === 0 || j === 6);
          const core = i >= 2 && i <= 4 && j >= 2 && j <= 4;
          g[rr][cc] = border || core;
        } else g[rr][cc] = false;
      }
    };
    finder(0, 0); finder(0, n - 7); finder(n - 7, 0);
    return g;
  }, [value]);
  const m = size / n;
  return (
    <div className="op-qr" style={{ width: size, height: size }}>
      <svg viewBox={`0 0 ${size} ${size}`}>
        {cells.map((row, r) => row.map((on, c) => on
          ? <rect key={r + "-" + c} x={c * m} y={r * m} width={m + 0.4} height={m + 0.4} rx={m * 0.16} fill="#10140f"/>
          : null))}
      </svg>
    </div>
  );
};

// ── Centered confirm modal ──
const Modal = ({ open, onClose, title, desc, children, actions, wide }) => {
  if (!open) return null;
  return (
    <div className="op-modal-scrim" onClick={(e) => { if (e.target === e.currentTarget) onClose && onClose(); }}>
      <div className={`op-modal ${wide ? "wide" : ""}`}>
        {title && <h3>{title}</h3>}
        {desc && <p>{desc}</p>}
        {children}
        {actions && <div className="op-modal-actions">{actions}</div>}
      </div>
    </div>
  );
};

// ── Supervisor override modal (§2.2 — PIN + reason) ──
const OverrideModal = ({ open, onClose, onConfirm, condition }) => {
  const [pin, setPin] = useState("");
  const [reason, setReason] = useState("");
  const ref = useRef(null);
  useEffect(() => { if (open) { setPin(""); setReason(""); setTimeout(() => ref.current?.focus(), 50); } }, [open]);
  if (!open) return null;
  return (
    <Modal open={open} onClose={onClose} title="Supervisor override required"
      desc={condition || "This action requires a supervisor. The override and the original condition are logged against the GPN."}>
      <div style={{ position: "relative" }} onClick={() => ref.current?.focus()}>
        <input ref={ref} inputMode="numeric" maxLength={4} value={pin}
          onChange={(e) => setPin(e.target.value.replace(/\D/g, "").slice(0, 4))}
          style={{ position: "absolute", opacity: 0, pointerEvents: "none", width: 1, height: 1 }}/>
        <div className="op-label">Supervisor PIN <span className="req">*</span></div>
        <div className="op-pin" style={{ marginBottom: 16 }}>
          {Array.from({ length: 4 }).map((_, i) => (
            <div key={i} className={`op-pin-cell ${pin[i] ? "filled" : ""} ${i === pin.length ? "cursor" : ""}`}>{pin[i] ? "•" : ""}</div>
          ))}
        </div>
      </div>
      <div className="op-field">
        <div className="op-label">Reason <span className="req">*</span></div>
        <textarea className="op-textarea" placeholder="Describe why the override is justified…" value={reason} onChange={(e) => setReason(e.target.value)}/>
      </div>
      <div className="op-modal-actions">
        <Btn variant="ghost" block onClick={onClose}>Cancel</Btn>
        <Btn variant="destructive" block disabled={pin.length < 4 || reason.trim().length < 3} onClick={onConfirm}>Authorize override</Btn>
      </div>
    </Modal>
  );
};

// ── Toast ──
const Toast = ({ show, icon: Icon = OpIc.CheckCircle, children }) =>
  show ? <div className="op-toast"><Icon size={18}/>{children}</div> : null;

// ── Stepper (C-124) ──
const Stepper = ({ steps, current }) => (
  <div className="op-stepper">
    {steps.map((s, i) => (
      <React.Fragment key={s}>
        {i > 0 && <span className={`op-step-sep ${i <= current ? "done" : ""}`}/>}
        <span className={`op-step-pip ${i < current ? "done" : i === current ? "cur" : ""}`}>
          <span className="op-step-num">{i < current ? <OpIc.Check size={14}/> : i + 1}</span>
          <span className="op-step-label">{s}</span>
        </span>
      </React.Fragment>
    ))}
  </div>
);

// ── Detail row ──
const SRow = ({ k, v, icon: Icon, sub }) => (
  <div className="op-srow">
    <span className="k">{Icon && <Icon size={15}/>}{k}</span>
    <span className="v">{v}{sub && <small> {sub}</small>}</span>
  </div>
);

// ── Order summary card (used across scan→verify flow) ──
const OrderCard = ({ order, compact }) => {
  const FD = window.OD;
  return (
    <div className="op-card flush">
      <div style={{ display: "flex", alignItems: "center", gap: 13, padding: "16px 16px 12px" }}>
        <span className={`op-row-thumb ${order.dir === "out" ? "soil" : ""}`} style={{ width: 48, height: 48 }}>
          {order.dir === "out" ? <OpIc.Truck size={22}/> : <OpIc.Leaf size={22}/>}
        </span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontSize: 17, fontWeight: 600, letterSpacing: "-0.01em" }}>{order.who}</span>
            {order.tier && order.tier !== "—" && <Pill tone={order.tier === "A" ? "approved" : order.tier === "new" ? "soil" : "closed"}>{FD.TIER_LABEL[order.tier]}</Pill>}
          </div>
          <div className="op-mono" style={{ fontSize: 12, color: "var(--muted-foreground)", marginTop: 2 }}>{order.id} · {order.location}</div>
        </div>
        <span className={`badge badge-${order.dir === "out" ? "soil" : "avocado"}`}>{order.dir === "out" ? "Outbound" : "Inbound"}</span>
      </div>
      {!compact && (
        <>
          <SRow k="Product" v={order.product} sub={order.grade ? "· " + order.grade : ""}/>
          <SRow k="Expected quantity" v={FD.KG(order.qty)}/>
          {/* Pricing hidden outside the Procurement module (org policy) — no rate/value shown at the gate. */}
          <SRow k="Delivery slot" v={order.slotWindow} sub={"· " + order.slotDate}/>
          <SRow k="Contact" v={order.phone}/>
        </>
      )}
    </div>
  );
};

window.Op = {
  Btn, Pill, Severity, Banner, Strip, Kpi, ToggleRow, NumInput, PhotoTile, QR,
  Modal, OverrideModal, Toast, Stepper, SRow, OrderCard,
};
