// ─────────────────────────────────────────────────────────────────────────────
// Farmer Mobile — shared UI primitives. Loads after icons/data, before pages.
// Declares the React hooks ONCE (global, reused by pages + shell, mirroring
// lib/ui.jsx). Exports reusable components on window.Fm. Page files reference
// these function-locally to avoid cross-file top-level name collisions.
// ─────────────────────────────────────────────────────────────────────────────

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

// App bar with optional back button + right-side actions.
const AppBar = ({ title, onBack, right, left, align = "center", className = "" }) => (
  <header className={`fm-appbar ${align === "left" ? "left" : ""} ${className}`}>
    {onBack
      ? <button className="fm-iconbtn" aria-label="Back" onClick={onBack}><FmIc.ChevronLeft size={24}/></button>
      : (left || (align === "center" ? <span style={{ width: 38, flexShrink: 0 }}/> : null))}
    <div className="fm-ab-title" style={align === "left" ? { textAlign: "left" } : null}>{title}</div>
    <div style={{ display: "flex", gap: 2, flexShrink: 0 }}>{right || <span style={{ width: 38 }}/>}</div>
  </header>
);

// Status pill — reuses AMOMS badge tokens.
const Pill = ({ status }) => {
  const map = {
    pending:   ["pending", "Pending"],
    accepted:  ["approved", "Accepted"],
    rejected:  ["closed", "Not selected"],
    responded: ["avocado", "Responded"],
    open:      ["info", "Open"],
    queued:    ["warning", "Queued"],
    new:       ["soil", "New"],
    urgent:    ["destructive", "Urgent"],
    confirmed: ["approved", "Confirmed"],
    withdrawn: ["closed", "Withdrawn"],
    signed:    ["approved", "Signed"],
  };
  const [tone, label] = map[status] || ["outline", status];
  return <span className={`badge badge-${tone}`}>{label}</span>;
};

// Deadline ticker — amber < 24h, red < 2h.
const Ticker = ({ hrs, label = "Closes" }) => {
  const tone = hrs < 2 ? "red" : hrs < 24 ? "amber" : "";
  let text;
  if (hrs < 1) text = `${Math.max(1, Math.round(hrs * 60))}m left`;
  else if (hrs < 24) text = `${Math.round(hrs)}h left`;
  else text = `${Math.round(hrs / 24)}d left`;
  return (
    <span className={`fm-deadline ${tone}`}>
      <FmIc.Clock size={14}/>
      <span className="fm-dl-label">{label}</span> {text}
    </span>
  );
};

// Deterministic QR-ish block (C-116) — faithful placeholder, not a scannable code.
const QR = ({ value = "GPN", size = 196 }) => {
  const n = 25;
  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="fm-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.18} fill="#10140f"/>
          : null))}
      </svg>
    </div>
  );
};

// 6-digit OTP input (stable component so focus survives re-renders).
const OtpInput = ({ value, onChange, err, autoFocus = true }) => {
  const ref = useRef(null);
  return (
    <div style={{ position: "relative" }} onClick={() => ref.current?.focus()}>
      <input ref={ref} inputMode="numeric" maxLength={6} value={value}
             onChange={(e) => onChange(e.target.value.replace(/\D/g, "").slice(0, 6))}
             style={{ position: "absolute", opacity: 0, pointerEvents: "none", height: 1, width: 1 }} autoFocus={autoFocus}/>
      <div className="fm-otp">
        {Array.from({ length: 6 }).map((_, i) => (
          <div key={i} className={`fm-otp-cell ${value[i] ? "filled" : ""} ${err ? "err" : ""} ${i === value.length && !err ? "cursor" : ""}`}>
            {value[i] || ""}
          </div>
        ))}
      </div>
    </div>
  );
};

const Btn = ({ variant = "primary", icon: Icon, loading, children, ...rest }) => (
  <button {...rest} className={`fm-btn fm-btn-${variant} ${rest.className || ""}`} disabled={rest.disabled || loading}>
    {loading ? <span className="spin"/> : (Icon ? <Icon size={18}/> : null)}
    {children}
  </button>
);

// Bottom sheet.
const Sheet = ({ open, onClose, title, children }) => {
  if (!open) return null;
  return (
    <div className="fm-sheet-scrim" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="fm-sheet">
        <div className="fm-sheet-grab"/>
        {title && <div className="fm-sheet-title">{title}</div>}
        {children}
      </div>
    </div>
  );
};

// Centered confirm modal.
const Modal = ({ open, onClose, title, children, actions }) => {
  if (!open) return null;
  return (
    <div className="fm-modal-scrim" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="fm-modal">
        {title && <h3>{title}</h3>}
        {children}
        {actions && <div className="fm-modal-actions">{actions}</div>}
      </div>
    </div>
  );
};

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

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

// Reusable read-only summary card for an offer (qty / rate / dates / notes).
const OfferSummary = ({ resp }) => {
  const FD = window.FD;
  return (
    <div className="fm-card flush">
      <div className="fm-srow"><span className="k">Quantity offered</span><span className="v">{FD.KG(resp.qty)}</span></div>
      <div className="fm-srow"><span className="k">Your rate</span><span className="v">{FD.KES(resp.rate)}<small> /kg</small></span></div>
      <div className="fm-srow"><span className="k">Preferred delivery</span><span className="v">{resp.deliveryDate}</span></div>
      {resp.altDate && <div className="fm-srow"><span className="k">Alternative date</span><span className="v">{resp.altDate}</span></div>}
      {resp.notes && <div className="fm-srow"><span className="k">Notes to buyer</span><span className="v" style={{ fontWeight: 400, maxWidth: 180 }}>{resp.notes}</span></div>}
    </div>
  );
};

window.Fm = { AppBar, Pill, Ticker, QR, OtpInput, Btn, Sheet, Modal, Banner, Toast, OfferSummary };
