/* ============================================================
   Carzello — responsive app shell + router
   ============================================================ */

const NAV = [
  { id: "browse", tkey: "nav.buy", icon: I.search, path: "/browse" },
  { id: "watchlist", tkey: "nav.watchlist", icon: I.star, path: "/watchlist" },
  { id: "activity", tkey: "nav.bids", icon: I.gavel, path: "/activity" },
  { id: "purchases", tkey: "nav.purchases", icon: I.truck, path: "/purchases" },
  { id: "account", tkey: "nav.account", icon: I.user, path: "/account" },
];

function unreadCount(s) { return s.notifications.filter(n => n.ts > s.notifReadAt).length; }
function activeBidsBadge(s) { return Object.values(s.lots).filter(L => L.yourMax != null && L.status === "live" && L.highBidder !== "you").length; }

function GlobalSearch({ onClose }) {
  const s = useStore();
  const [q, setQ] = useState("");
  const [copart, setCopart] = useState([]);
  const inputRef = useRef(null);
  useEffect(() => { inputRef.current?.focus(); }, []);
  const results = q ? Object.values(s.lots).filter(L => !L.hidden && `${L.year} ${L.make} ${L.model} ${L.trim} ${L.vin} ${L.id}`.toLowerCase().includes(q.toLowerCase())).slice(0, 8) : [];
  // the Copart feed is part of what's on the page — search must cover it too
  useEffect(() => {
    if (!q.trim()) { setCopart([]); return; }
    const t = setTimeout(() => {
      fetch(`/api/copart/sales-data?search=${encodeURIComponent(q.trim())}&limit=6`)
        .then((r) => r.json())
        .then((d) => setCopart(d.success ? d.data : []))
        .catch(() => setCopart([]));
    }, 350);
    return () => clearTimeout(t);
  }, [q]);
  return (
    <Modal onClose={onClose}>
      <div className="mhead" style={{ gap: 10 }}>
        <I.search width="16" height="16" style={{ color: "var(--fg-3)" }} />
        <input ref={inputRef} className="input" style={{ border: 0, padding: 0, fontSize: 16 }} placeholder="Search VIN, make, model, lot ID…" value={q} onChange={(e) => setQ(e.target.value)}
          onKeyDown={(e) => { if (e.key === "Enter" && results[0]) { navigate(`/lot/${results[0].id}`); onClose(); } }} />
        <span className="kbd" style={{ fontFamily: "var(--mono)", fontSize: 11, color: "var(--fg-4)" }}>esc</span>
      </div>
      <div className="mbody" style={{ padding: 0, maxHeight: 400, overflowY: "auto" }}>
        {q && results.length === 0 && copart.length === 0 && <div className="muted" style={{ padding: 20, textAlign: "center" }}>No matches for "{q}"</div>}
        {results.map(L => (
          <div key={L.id} className="row gap-12" style={{ padding: "11px 16px", borderTop: "1px solid var(--border)", cursor: "pointer" }} onClick={() => { navigate(`/lot/${L.id}`); onClose(); }}>
            <Photo style={{ width: 56, borderRadius: 7 }} hue={L.id.charCodeAt(5) * 6} />
            <div style={{ flex: 1 }}><b style={{ fontSize: 14 }}>{L.year} {L.make} {L.model}</b><div className="muted" style={{ fontSize: 12 }}>{L.trim} · {L.id}</div></div>
            <div style={{ textAlign: "right" }}><b className="tnum">{fmtUSD(L.highBid)}</b><div className="muted" style={{ fontSize: 11 }}><GradeChip score={L.autograde} /></div></div>
          </div>
        ))}
        {copart.length > 0 && (
          <>
            <div className="row gap-8" style={{ padding: "9px 16px", borderTop: "1px solid var(--border)", background: "var(--surface-2)" }}>
              <Pill kind="red" style={{ fontSize: 9.5 }}>COPART DATA</Pill>
              <span className="muted" style={{ fontSize: 11.5 }}>sourcing candidates — request a quote</span>
            </div>
            {copart.map((v) => (
              <div key={v.lotNumber} className="row gap-12" style={{ padding: "11px 16px", borderTop: "1px solid var(--border)", cursor: "pointer" }}
                onClick={() => { openCopartLot(v); onClose(); }}>
                <div style={{ flex: 1 }}><b style={{ fontSize: 14 }}>{copartTitle(v)}</b><div className="muted" style={{ fontSize: 12 }}>{Number(v.odometer || 0).toLocaleString("en-US")} mi · {v.damageDescription || "—"} · Lot {v.lotNumber}</div></div>
                <b className="tnum" style={{ fontSize: 13 }}>{fmtUSD(Number(v.estRetailValue) || 0)}</b>
              </div>
            ))}
          </>
        )}
        {!q && <div className="muted" style={{ padding: 20, fontSize: 13 }}>Type to search the wholesale inventory and the Copart feed.</div>}
      </div>
    </Modal>
  );
}

const FAQS = [
  { q: "How does proxy bidding work?", a: "Set the maximum you're willing to pay. The system bids the minimum needed to keep you in the lead, one increment above the next-highest bidder, never exceeding your max. Your max is never revealed." },
  { q: "What are the fees?", a: "A fixed $345 buyer fee and $170 title & inspection on every vehicle — disclosed before you bid. Freight, duty, and VAT for your destination are shown as an estimate in the landed-cost panel on every lot." },
  { q: "When do I have to pay?", a: "Payment in full is due within 48 hours of winning. After that a $50/day late fee applies; unpaid orders default after 5 days — the vehicle is relisted and a penalty of 10% or $800 (whichever is greater) is charged." },
  { q: "What is the gate pass?", a: "Once your payment clears, the system issues a gate pass — present it at the yard to release your vehicle. Pick up within 7 days; storage is $25/day afterwards." },
  { q: "What if the car doesn't match the condition report?", a: "Every lot is inspected and AutoGraded, and the condition is guaranteed to match the report. You have a 48-hour arbitration window from delivery to file a claim, plus optional Sayarah Assurance buyback at checkout." },
  { q: "What does 'reserve not met' mean?", a: "The seller set a minimum price the bidding didn't reach. If you were the high bidder, your bid is sent to the seller as an if-sale — they can accept it, counter, or decline. You can also make a direct offer on any lot." },
  { q: "How does shipping work?", a: "Sayarah handles export logistics door-to-port: gate release, trucking to port, ocean freight, and destination customs guidance. You can track milestones and documents in My Purchases." },
];
function HelpPage() {
  const [open, setOpen] = useState(0);
  return (
    <div className="fadein" style={{ maxWidth: 760 }}>
      <div className="pagehead"><span className="eyebrow">Support</span><h1 className="h1">How Sayarah <span className="accent">works</span></h1><div className="sub">Bidding, fees, payment, shipping, and arbitration — the whole deal, in plain terms.</div></div>
      <div className="card">
        {FAQS.map((f, i) => (
          <div key={i} style={{ borderTop: i ? "1px solid var(--border)" : "none" }}>
            <button className="row gap-10" style={{ width: "100%", padding: "15px 18px", background: "none", border: 0, textAlign: "start" }} onClick={() => setOpen(open === i ? -1 : i)} aria-expanded={open === i}>
              <b style={{ fontSize: 14.5, flex: 1 }}>{f.q}</b>
              <I.chevD width="15" height="15" style={{ transform: open === i ? "rotate(180deg)" : "none", transition: ".2s", flexShrink: 0 }} />
            </button>
            {open === i && <div className="muted fadein" style={{ padding: "0 18px 16px", fontSize: 13.5, lineHeight: 1.6 }}>{f.a}</div>}
          </div>
        ))}
      </div>
      <div className="card card-pad" style={{ marginTop: 16 }} id="privacy">
        <b style={{ fontSize: 14 }}>Privacy notice (summary)</b>
        <ul className="muted" style={{ fontSize: 12.5, lineHeight: 1.7, margin: "8px 0 0", paddingInlineStart: 18 }}>
          <li><b>What we collect:</b> dealer/consignor business details, contact information, trade-license and identity documents, transaction and bidding history.</li>
          <li><b>Why:</b> operating your account, running auctions and settlements, and meeting our legal obligations (know-your-customer, anti-money-laundering, sanctions screening, and export filings).</li>
          <li><b>Retention:</b> customer-due-diligence and transaction records are kept a minimum of 5 years after the relationship ends, as required by AML law; other data only as long as needed.</li>
          <li><b>Sharing & transfers:</b> with screening providers, freight forwarders, and authorities where required. Cross-border transfers use appropriate safeguards per UAE/KSA data-protection law.</li>
          <li><b>Your rights:</b> access, correction, and deletion (where not overridden by retention law) — contact support@sayarah.io.</li>
        </ul>
      </div>
      <div className="card card-pad" style={{ marginTop: 16 }}>
        <b style={{ fontSize: 14 }}>Terms of sale (summary)</b>
        <ul className="muted" style={{ fontSize: 12.5, lineHeight: 1.7, margin: "8px 0 0", paddingInlineStart: 18 }}>
          <li>All bids are binding and cannot be retracted once confirmed.</li>
          <li>Condition is guaranteed to match the published AutoGrade condition report; items listed as "not inspected" are excluded.</li>
          <li>Payment terms: 48h to pay · $50/day late · default after 5 days (relist + max(10%, $800) penalty) · $25/day storage after the 7-day pickup grace.</li>
          <li>Arbitration: 7 calendar days from delivery (extended for structural, flood/fire, odometer, and title/VIN issues; +7 days with post-sale inspection). Defects must exceed $800 repair cost, or 2% of price on $50,000+ vehicles. Vehicles at $3,000 or below sell as-is.</li>
          <li>Sale lights: green = ride &amp; drive guarantee · yellow = sold with announcements · red = as-is.</li>
          <li>Freight, duty, and VAT figures are estimates; final costs may vary.</li>
        </ul>
      </div>
    </div>
  );
}

function Footer() {
  return (
    <footer className="site-footer no-print">
      <div className="inner">
        <div className="cols">
          <div>
            <div className="fname">Carzello</div>
            <div className="fdesc">Our own inventory plus consigned vehicles — graded, guaranteed, and priced to your door in the GCC & Central Asia.</div>
            <div className="fbar" />
          </div>
          <div>
            <b>Marketplace</b>
            <a href="#/browse">Buy vehicles</a>
            <a href="#/consignor">Sell / consign</a>
            <a href="#/watchlist">Watchlist</a>
          </div>
          <div>
            <b>Support</b>
            <a href="#/help">How it works · FAQ</a>
            <a href="#/help">Terms of sale</a>
            <a href="#/help">Privacy notice</a>
            <a href="#/purchases">Payments & gate pass</a>
          </div>
          <div>
            <b>Contact</b>
            <a href="https://wa.me/18576055533" target="_blank" rel="noreferrer">WhatsApp · +1 (857) 605-5533</a>
            <a href="mailto:support@sayarah.io">support@sayarah.io</a>
            <span className="floc">Dubai · Dallas · Tashkent</span>
          </div>
        </div>
        <div className="base">
          © 2026 Sayarah Inc. Carzello, Atlantic Car Connect, Sayarah Auto, Sayarah Capital, Sayarah Gas, Sayarah Estates, and Sayarah FMCG are brands and trademarks of Sayarah Inc. · All fees disclosed before bid · 48h arbitration · AutoGrade condition guarantee.
        </div>
      </div>
    </footer>
  );
}

/* ============================================================
   Operator console loader — the admin source is NOT shipped to
   buyers. Verified operators fetch /app/admin.jsx with their
   Firebase token (server-enforced), compile it, and mount it.
   ============================================================ */
function OperatorGate({ err }) {
  const [email, setEmail] = useState("");
  const [pw, setPw] = useState("");
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState(err || null);
  function go() {
    if (busy) return;
    setMsg(null); setBusy(true);
    const enter = (cred) => {
      if (!FB.isAdmin(cred.user)) { setMsg("This account does not have operator access."); setBusy(false); return FB.signOut(); }
      return FB.adoptAccountState().then(() => location.reload());
    };
    FB.signIn(email, pw)
      .then(enter)
      .catch((e) => {
        if (FB.ADMIN_EMAILS.includes(email.toLowerCase().trim())) {
          return FB.signUp(email, pw).then(enter).catch((e2) => { setMsg(/already exists/i.test(e2.message) ? e.message : e2.message); setBusy(false); });
        }
        setMsg(e.message); setBusy(false);
      });
  }
  return (
    <div className="gate">
      <div className="card">
        <div className="row gap-10" style={{ marginBottom: 18 }}>
          <div><img src="assets/carzello-logo.svg" alt="Carzello" style={{ height: 26, display: "block", marginBottom: 6 }} /><div className="muted" style={{ fontSize: 12, letterSpacing: ".1em", textTransform: "uppercase", fontWeight: 700 }}>Operator console</div></div>
        </div>
        <div className="col gap-12">
          <div className="field"><label>Work email</label><input className="input" type="email" name="email" value={email} onChange={(e) => setEmail(e.target.value)} autoComplete="email" /></div>
          <div className="field"><label>Password</label><input className="input" type="password" name="password" value={pw} onChange={(e) => { setPw(e.target.value); setMsg(null); }} onKeyDown={(e) => e.key === "Enter" && go()} autoComplete="current-password" /></div>
          {msg && <div className="feedback err"><I.alert width="13" height="13" /> {msg}</div>}
          <button className="btn primary lg block" onClick={go} disabled={busy}><I.shield width="14" height="14" /> {busy ? "Signing in…" : "Sign in"}</button>
          <div className="muted" style={{ fontSize: 12, textAlign: "center" }}>Operator accounts only. <a href="#/browse" style={{ color: "var(--brand)", fontWeight: 700 }}>Back to buyer site</a></div>
        </div>
      </div>
    </div>
  );
}

function AdminLoader({ section, sub }) {
  const user = useAuthUser();
  const [ready, setReady] = useState(() => typeof window.Admin === "function");
  const [err, setErr] = useState(null);
  const isOp = FB.enabled && FB.isAdmin(user);
  useEffect(() => {
    if (ready || !isOp) return;
    let dead = false;
    FB.currentUser().getIdToken()
      .then((tk) => fetch("/app/admin.jsx", { headers: { authorization: "Bearer " + tk } }))
      .then((r) => { if (!r.ok) throw new Error("Operator verification failed."); return r.text(); })
      .then((code) => {
        const js = Babel.transform(code, { presets: ["react"], filename: "admin.jsx" }).code;
        (0, eval)(js);
        if (!dead) setReady(typeof window.Admin === "function");
      })
      .catch((e) => { if (!dead) setErr(e.message || "Could not load the console."); });
    return () => { dead = true; };
  }, [isOp, ready]);
  if (ready) return <window.Admin section={section} sub={sub} />;
  if (isOp && !err) return <div className="gate"><div className="muted" style={{ fontWeight: 700, letterSpacing: ".08em", textTransform: "uppercase" }}>Loading operator console…</div></div>;
  return <OperatorGate err={err} />;
}

function App() {
  const route = useRoute();
  const s = useStore();
  const { t } = useT();
  const [searchOpen, setSearchOpen] = useState(false);
  const user = useAuthUser();
  const [authOpen, setAuthOpen] = useState(false);

  // sign-in modal opens on the global event fired by requireAuth()
  useEffect(() => {
    const open = () => setAuthOpen(true);
    window.addEventListener("carzello:auth", open);
    return () => window.removeEventListener("carzello:auth", open);
  }, []);

  // keep the buyer identity in sync with the signed-in account
  useEffect(() => {
    if (user && user.email && s.buyer && s.buyer.email !== user.email) {
      Engine.setBuyerIdentity({ name: user.displayName || user.email.split("@")[0], email: user.email });
    }
  }, [user && user.uid]);

  useEffect(() => {
    const on = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); setSearchOpen(true); }
    };
    window.addEventListener("keydown", on); return () => window.removeEventListener("keydown", on);
  }, []);
  // scroll to top on route change
  useEffect(() => { window.scrollTo(0, 0); }, [route.name, route.param]);

  // Admin / consignor portals render their own full-screen shells (no buyer chrome)
  if (route.name === "admin") return (<><AdminLoader section={route.param} sub={route.sub} /><ToastHost /></>);
  if (route.name === "consignor") return (<><Consignor section={route.param} /><ToastHost /></>);

  const unread = unreadCount(s);
  const bidsBadge = activeBidsBadge(s);

  function screen() {
    switch (route.name) {
      case "browse": return <Browse />;
      case "lot": return <Lot id={route.param} />;
      case "live": return <LiveRoom id={route.param} />;
      case "watchlist": return <Watchlist />;
      case "activity": return <Activity />;
      case "purchases": return <Purchases />;
      case "notifications": return <Notifications />;
      case "account": return <Account />;
      case "sell": return <Sell />;
      case "help": return <HelpPage />;
      default: return <Browse />;
    }
  }

  const navActive = (id) => {
    if (route.name === "lot" || route.name === "live") return id === "browse";
    return route.name === id;
  };

  return (
    <div className="app">
      {/* TOP BAR */}
      <header className="topbar">
        <a className="logo" href="#/browse"><img className="logo-img" src="assets/carzello-logo.svg" alt="Carzello" /></a>
        <nav className="topnav hide-sm">
          {NAV.map(n => (
            <a key={n.id} href={"#" + n.path} className={navActive(n.id) ? "on" : ""}>
              <n.icon width="15" height="15" />{t(n.tkey)}
              {n.id === "activity" && bidsBadge > 0 && <span className="badge">{bidsBadge}</span>}
            </a>
          ))}
        </nav>
        <button className="topsearch hide-sm" onClick={() => setSearchOpen(true)} style={{ cursor: "text" }}>
          <I.search width="15" height="15" /><span style={{ flex: 1, textAlign: "start", color: "var(--fg-4)" }}>{t("search.placeholder")}</span><span className="kbd">⌘K</span>
        </button>
        <div className="right">
          <button className="iconbtn mob-only" aria-label="Search" onClick={() => setSearchOpen(true)}><I.search width="16" height="16" /></button>
          <LangSwitch />
          <a className="iconbtn hide-sm" href="#/sell" title="Sell"><I.plus width="17" height="17" /></a>
          <a className="iconbtn" href="#/notifications" title="Notifications">
            <I.bell width="17" height="17" />{unread > 0 && <span className="dot" />}
          </a>
          {user
            ? <a className="avatar" href="#/account" title={user.email}>
                {(user.displayName || user.email || "?").trim().split(/[\s@.]+/).slice(0, 2).map(w => w[0]).join("").toUpperCase()}
              </a>
            : <button className="btn primary sm" onClick={() => setAuthOpen(true)}>Sign in</button>}
        </div>
      </header>

      {/* WORKSPACE */}
      <main className="main">{screen()}</main>
      <Footer />

      {/* BOTTOM TAB BAR (mobile) */}
      <nav className="tabbar">
        {NAV.map(n => (
          <a key={n.id} href={"#" + n.path} className={navActive(n.id) ? "on" : ""}>
            <n.icon width="20" height="20" />{t(n.tkey)}
            {n.id === "activity" && bidsBadge > 0 && <span className="tbadge">{bidsBadge}</span>}
          </a>
        ))}
      </nav>

      {searchOpen && <GlobalSearch onClose={() => setSearchOpen(false)} />}
      {authOpen && <AuthModal onClose={() => setAuthOpen(false)} />}
      <CopartLotModalHost />
      <ToastHost />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
