// SSPHONE shell — sidebar, topbar, routing, สลับผู้ใช้/สาขา
const NAV = [
  { key: "dashboard", icon: "▦", label: "แดชบอร์ด" },
  { key: "income", icon: "▰", label: "รายรับรายวัน" },
  { key: "pos", icon: "▥", label: "ขายสินค้า (POS)" },
  { key: "pos_wholesale", icon: "▤", label: "ขายส่ง (POS)" },
  { key: "buyin", icon: "⇲", label: "รับซื้อ / รับเทิร์น" },
  { key: "pawns", icon: "◈", label: "จำนำ" },
  { key: "repairs", icon: "🔧", label: "งานซ่อม" },
  { key: "stock", icon: "📦", label: "สต็อกสินค้า" },
  { key: "parts", icon: "⚙", label: "สต็อกอะไหล่" },
  { key: "locations", icon: "📍", label: "คลัง & Location" },
  { key: "reports", icon: "📊", label: "รายงาน" },
  { key: "branches", icon: "⌂", label: "สาขา" },
  { key: "staff", icon: "◉", label: "พนักงาน & สิทธิ์" },
];

const PAGES = {
  dashboard: () => window.DashboardPage, income: () => window.IncomePage, pos: () => window.PosPage, pos_wholesale: () => window.PosPage, invoices: () => window.InvoicesPage, buyin: () => window.BuyinPage, pawns: () => window.PawnsPage, repairs: () => window.RepairsPage,
  stock: () => window.StockPage, parts: () => window.PartsPage, locations: () => window.LocationsPage, reports: () => window.ReportsPage,
  branches: () => window.BranchesPage, staff: () => window.StaffPage, settings: () => window.SettingsPage,
};
const SETTINGS_NAV = { key: "settings", icon: "⚙", label: "ตั้งค่าระบบ" };
const INVOICES_NAV = { key: "invoices", icon: "📄", label: "ใบกำกับภาษี" };

// ── ศูนย์แจ้งเตือน — สินค้าใกล้หมด / งานซ่อมถึงนัด / จำนำครบกำหนด ──
function buildNotifications(st, scope, allowed) {
  const today0 = new Date(); today0.setHours(0, 0, 0, 0);
  const t0 = today0.getTime();
  const DAY = 86400000;
  const inScope = (b) => scope === "ALL" || b === scope;
  const dueWord = (due) => {
    const days = Math.round((due - t0) / DAY);
    if (days < 0) return { txt: `เลยกำหนด ${Math.abs(days)} วัน`, tone: "danger" };
    if (days === 0) return { txt: "ครบกำหนดวันนี้", tone: "warn" };
    return { txt: `อีก ${days} วัน`, tone: "warn" };
  };
  const out = [];

  // 1) สินค้า/อะไหล่ใกล้หมด (เฉพาะที่มีจุดสั่งซื้อ)
  if (allowed.includes("stock") || allowed.includes("parts")) {
    (st.products || []).forEach((p) => {
      if (!p.reorder || p.reorder <= 0) return;
      const qty = scope === "ALL" ? stockTotal(p) : stockInBranch(st, p, scope);
      if (qty > p.reorder) return;
      const isPart = p.cat === "อะไหล่";
      if (isPart && !allowed.includes("parts")) return;
      if (!isPart && !allowed.includes("stock")) return;
      out.push({
        id: "low-" + p.id, group: "stock", tone: qty === 0 ? "danger" : "warn", icon: "📦",
        title: p.name,
        sub: qty === 0 ? "สินค้าหมด — ควรเติมด่วน" : `เหลือ ${qty} ชิ้น (จุดสั่งซื้อ ${p.reorder})`,
        page: isPart ? "parts" : "stock", param: null, sort: qty === 0 ? 0 : 1,
      });
    });
  }

  // 2) งานซ่อมถึงกำหนดนัดรับ / เลยกำหนด (ยังไม่ส่งมอบ)
  if (allowed.includes("repairs")) {
    (st.repairs || []).forEach((r) => {
      if (!inScope(r.branch)) return;
      if (r.status === "ส่งมอบแล้ว") return;
      if (r.due == null || r.due >= t0 + DAY) return;
      const w = dueWord(r.due);
      out.push({
        id: "rp-" + r.id, group: "repair", tone: w.tone, icon: "🔧",
        title: `${r.id} · ${r.customer} — ${r.device}`,
        sub: `นัดรับ ${w.txt} · สถานะ: ${r.status}`,
        page: "repairs", param: r.id, sort: w.tone === "danger" ? 0 : 1,
      });
    });
  }

  // 3) จำนำครบกำหนด / เลยกำหนด (ภายใน 3 วัน)
  if (allowed.includes("pawns")) {
    (st.pawns || []).forEach((p) => {
      if (p.status !== "active") return;
      if (!inScope(p.branch)) return;
      if (p.due == null || p.due >= t0 + 3 * DAY) return;
      const w = dueWord(p.due);
      out.push({
        id: "pw-" + p.id, group: "pawn", tone: w.tone, icon: "◈",
        title: `${p.id} · ${p.customer || "-"} — ${p.model}`,
        sub: `ครบกำหนดไถ่ถอน ${w.txt}`,
        page: "pawns", param: null, sort: w.tone === "danger" ? 0 : 1,
      });
    });
  }

  out.sort((a, b) => a.sort - b.sort);
  return out;
}

function NotificationBell({ st, scope, allowed, go }) {
  const [open, setOpen] = React.useState(false);
  const items = React.useMemo(() => buildNotifications(st, scope, allowed), [st, scope, allowed]);
  const count = items.length;
  const groups = [
    { key: "stock", label: "สินค้าใกล้หมด", items: items.filter((i) => i.group === "stock") },
    { key: "repair", label: "งานซ่อมถึงนัดรับ", items: items.filter((i) => i.group === "repair") },
    { key: "pawn", label: "จำนำครบกำหนด", items: items.filter((i) => i.group === "pawn") },
  ].filter((g) => g.items.length);
  const toneColor = (t) => (t === "danger" ? T.accent : "#E8833A");

  return (
    <div style={{ position: "relative" }}>
      <div title="การแจ้งเตือน" onClick={() => setOpen((o) => !o)} style={{ width: 36, height: 36, borderRadius: 10, background: open ? T.primary : T.chipBg, color: open ? "#fff" : T.text, border: `1px solid ${open ? T.primary : T.border}`, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 15, position: "relative", cursor: "pointer" }}>
        🔔
        {count > 0 && (
          <span style={{ position: "absolute", top: -5, right: -5, minWidth: 17, height: 17, padding: "0 4px", borderRadius: 999, background: T.accent, color: "#fff", fontSize: 10.5, fontWeight: 800, display: "flex", alignItems: "center", justifyContent: "center", boxShadow: "0 1px 4px rgba(0,0,0,.3)" }}>{count > 99 ? "99+" : count}</span>
        )}
      </div>
      {open && (
        <React.Fragment>
          <div onClick={() => setOpen(false)} style={{ position: "fixed", inset: 0, zIndex: 80 }}></div>
          <div style={{ position: "absolute", top: 46, right: 0, width: 360, maxHeight: "min(70vh, 560px)", overflowY: "auto", background: T.surface, border: `1px solid ${T.border}`, borderRadius: 16, boxShadow: "0 18px 50px rgba(0,0,0,.30)", zIndex: 90 }}>
            <div style={{ position: "sticky", top: 0, background: T.surface, padding: "14px 16px 10px", borderBottom: `1px solid ${T.border}`, display: "flex", alignItems: "center", gap: 8, zIndex: 1 }}>
              <span style={{ fontFamily: T.headFont, fontWeight: 800, fontSize: 15 }}>การแจ้งเตือน</span>
              {count > 0 && <span style={{ fontSize: 11.5, fontWeight: 700, color: "#fff", background: T.accent, borderRadius: 999, padding: "1px 9px" }}>{count}</span>}
            </div>
            {count === 0 ? (
              <div style={{ padding: "38px 20px", textAlign: "center", color: T.sub }}>
                <div style={{ fontSize: 30, marginBottom: 8 }}>✓</div>
                <div style={{ fontSize: 13, fontWeight: 600 }}>ไม่มีรายการที่ต้องดำเนินการ</div>
                <div style={{ fontSize: 11.5, marginTop: 4 }}>สินค้า งานซ่อม และจำนำ อยู่ในเกณฑ์ปกติ</div>
              </div>
            ) : (
              groups.map((g) => (
                <div key={g.key}>
                  <div style={{ padding: "10px 16px 4px", fontSize: 11, fontWeight: 800, letterSpacing: 0.4, color: T.sub, textTransform: "uppercase" }}>{g.label} · {g.items.length}</div>
                  {g.items.map((it) => (
                    <div key={it.id} className="ss-row" onClick={() => { go(it.page, it.param); setOpen(false); }} style={{ display: "flex", gap: 11, alignItems: "flex-start", padding: "10px 16px", cursor: "pointer", borderLeft: `3px solid ${toneColor(it.tone)}` }}>
                      <div style={{ width: 30, height: 30, flex: "none", borderRadius: 8, background: T.chipBg, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 15 }}>{it.icon}</div>
                      <div style={{ minWidth: 0, flex: 1 }}>
                        <div style={{ fontSize: 12.8, fontWeight: 700, color: T.text, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{it.title}</div>
                        <div style={{ fontSize: 11.5, color: toneColor(it.tone), fontWeight: 600, marginTop: 1 }}>{it.sub}</div>
                      </div>
                    </div>
                  ))}
                </div>
              ))
            )}
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

function loadUi() {
  try { const v = JSON.parse(localStorage.getItem("ssphone-ui")); if (v && v.userId) return v; } catch (e) {}
  return { userId: "U1", page: "dashboard", branch: "ALL" };
}

function Shell() {
  const { st, dispatch } = useStore();
  const toast = useToast();
  useTheme(); // re-render ทั้ง shell เมื่อเปลี่ยนธีมสี
  const [ui, setUi] = React.useState(loadUi);
  const [switchOpen, setSwitchOpen] = React.useState(false);
  const [pageReady, setPageReady] = React.useState(false);
  
  React.useEffect(() => { try { localStorage.setItem("ssphone-ui", JSON.stringify({ userId: ui.userId, page: ui.page, branch: ui.branch })); } catch (e) {} }, [ui]);

  const user = st.users.find((u) => u.id === ui.userId) || st.users[0];
  const role = st.roles[user.role];
  const allowed = role.pages;
  const page = allowed.includes(ui.page) ? ui.page : "dashboard";
  const go = (p, param) => setUi((x) => ({ ...x, page: p, param }));
  React.useEffect(() => {
    if (ui.branch !== "ALL" && !st.branches.some((b) => b.id === ui.branch)) setUi((x) => ({ ...x, branch: "ALL" }));
  }, [st.branches.length]);
  React.useEffect(() => {
    if (!role.allBranch && ui.branch !== user.branch) setUi((x) => ({ ...x, branch: user.branch }));
  }, [ui.userId]);

  const switchUser = (u) => {
    setUi((x) => ({ ...x, userId: u.id, page: "dashboard", branch: st.roles[u.role].allBranch ? "ALL" : u.branch }));
    setSwitchOpen(false);
    toast(`สลับผู้ใช้เป็น ${u.name} (${st.roles[u.role].label})`, "info");
  };

  React.useEffect(() => {
    setPageReady(!!PAGES[page]?.());
  }, [page]);

  const PageComponent = PAGES[page]?.();
  const brOpts = [{ value: "ALL", label: "ทุกสาขา (รวม)" }, ...st.branches.map((b) => ({ value: b.id, label: b.name }))];
  const navTitle = page === "settings" ? "ตั้งค่าระบบ" : (NAV.find((n) => n.key === page) || {}).label;

  return (
    <div className="app-shell" style={{ display: "flex", height: "100vh", background: T.bg, fontFamily: T.bodyFont, color: T.text, overflow: "hidden" }}>
      {/* ── Sidebar ── */}
      <div style={{ width: 232, flex: "none", background: T.sideBg, display: "flex", flexDirection: "column", padding: "20px 13px 14px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "0 8px 20px" }}>
          <div style={{ width: 40, height: 40, borderRadius: 11, background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", boxShadow: "0 4px 14px rgba(0,0,0,.3)" }}>
            <img src={logoSrc(st)} alt="logo" style={{ width: 34, height: 34, objectFit: "contain" }} />
          </div>
          <div>
            <div style={{ fontFamily: T.headFont, fontWeight: 800, fontSize: 16.5, color: T.sideText, letterSpacing: 0.5 }}>{shopName(st)}</div>
            <div style={{ fontSize: 10.5, color: T.sideMuted }}>{st.settings.tagline || "ระบบบริหารร้านมือถือ"}</div>
          </div>
        </div>
        <div className="ss-no-sb" style={{ display: "flex", flexDirection: "column", gap: 3, flex: 1, overflowY: "auto" }}>
          {NAV.filter((n) => allowed.includes(n.key)).map((n) => {
            const active = page === n.key;
            return (
              <div key={n.key} className="ss-nav" onClick={() => go(n.key)} style={{
                display: "flex", alignItems: "center", gap: 11, padding: "10px 12px",
                borderRadius: 11, fontSize: 13.5, fontWeight: active ? 700 : 500, cursor: "pointer",
                background: active ? T.sideActiveBg : "transparent",
                color: active ? "#fff" : T.sideText,
                boxShadow: active ? "0 6px 16px rgba(46,99,231,.45)" : "none",
                transition: "background .18s, color .18s",
              }}>
                <span style={{ fontSize: 15, width: 19, textAlign: "center" }}>{n.icon}</span>{n.label}
              </div>
            );
          })}
        </div>
        {/* ใบกำกับภาษี — ด้านล่าง เฉพาะเจ้าของร้าน/ผู้จัดการ */}
        {allowed.includes("invoices") && (
          <div className="ss-nav" onClick={() => go("invoices")} style={{
            display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", marginTop: 4,
            borderRadius: 11, fontSize: 13.5, fontWeight: page === "invoices" ? 700 : 500, cursor: "pointer",
            background: page === "invoices" ? T.sideActiveBg : "transparent",
            color: page === "invoices" ? "#fff" : T.sideText,
            boxShadow: page === "invoices" ? "0 6px 16px rgba(46,99,231,.45)" : "none",
            borderTop: "1px solid rgba(255,255,255,.10)",
          }}>
            <span style={{ fontSize: 15, width: 19, textAlign: "center" }}>{INVOICES_NAV.icon}</span>{INVOICES_NAV.label}
          </div>
        )}
        {/* ตั้งค่าระบบ — ด้านล่าง เฉพาะเจ้าของร้าน */}
        {allowed.includes("settings") && (
          <div className="ss-nav" onClick={() => go("settings")} style={{
            display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", marginTop: 4,
            borderRadius: 11, fontSize: 13.5, fontWeight: page === "settings" ? 700 : 500, cursor: "pointer",
            background: page === "settings" ? T.sideActiveBg : "transparent",
            color: page === "settings" ? "#fff" : T.sideText,
            boxShadow: page === "settings" ? "0 6px 16px rgba(46,99,231,.45)" : "none",
            borderTop: "1px solid rgba(255,255,255,.10)",
          }}>
            <span style={{ fontSize: 15, width: 19, textAlign: "center" }}>{SETTINGS_NAV.icon}</span>{SETTINGS_NAV.label}
          </div>
        )}
        <DailyClearLauncher user={user} />
        <div className="ss-nav" onClick={() => setSwitchOpen(true)} style={{ display: "flex", alignItems: "center", gap: 10, padding: "11px 9px", borderTop: "1px solid rgba(255,255,255,.10)", cursor: "pointer", borderRadius: 11, marginTop: 8 }}>
          <Avatar name={user.name} img={user.img} size={34} />
          <div style={{ lineHeight: 1.3, minWidth: 0 }}>
            <div style={{ fontSize: 12.5, fontWeight: 700, color: T.sideText, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{user.name}</div>
            <div style={{ fontSize: 10.5, color: T.sideMuted }}>{role.label} · {role.allBranch ? "ทุกสาขา" : branchOf(st, user.branch).short}</div>
          </div>
          <span style={{ marginLeft: "auto", color: T.sideMuted, fontSize: 13 }}>⇄</span>
        </div>
      </div>

      {/* ── Main ── */}
      <div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
        <div style={{ height: 60, flex: "none", display: "flex", alignItems: "center", gap: 13, padding: "0 24px", background: T.surface, borderBottom: `1px solid ${T.border}`, position: "relative", zIndex: 60 }}>
          <div style={{ fontFamily: T.headFont, fontSize: 18, fontWeight: 700, whiteSpace: "nowrap" }}>
            {navTitle}
          </div>
          {role.allBranch ? (
            <Select value={ui.branch} onChange={(v) => setUi((x) => ({ ...x, branch: v }))} options={brOpts}
              style={{ width: 170, padding: "6px 10px", fontSize: 12.5, fontWeight: 700, color: T.primary, borderRadius: 999, background: T.chipBg, border: `1px solid ${T.border}` }} />
          ) : (
            <span style={{ fontSize: 12.5, fontWeight: 700, color: T.primary, background: T.chipBg, border: `1px solid ${T.border}`, borderRadius: 999, padding: "6px 14px", whiteSpace: "nowrap" }}>
              ⌂ {branchOf(st, user.branch).name}
            </span>
          )}
          <div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 10 }}>
            {allowed.includes("pos") && page !== "pos" && <Btn sm onClick={() => go("pos")}>⊕ ขายด่วน</Btn>}
            <ThemePicker />
            <NotificationBell st={st} scope={role.allBranch ? ui.branch : user.branch} allowed={allowed} go={go} />
          </div>
        </div>

        <div key={page + ui.branch} className="ss-page" style={{ flex: 1, overflowY: "auto", padding: 22 }}>
          {PageComponent ? (
            <PageComponent ui={{ ...ui, page }} go={go} user={user} />
          ) : (
            <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", color: T.sub }}>⏳ Loading…</div>
          )}
        </div>
      </div>

      {/* ── สลับผู้ใช้ ── */}
      <Modal open={switchOpen} onClose={() => setSwitchOpen(false)} title="สลับผู้ใช้ (ทดลองสิทธิ์แต่ละระดับ)" width={480}
        footer={<React.Fragment>
          <Btn kind="dangerSoft" sm onClick={() => { window.__ssLogout && window.__ssLogout(); setSwitchOpen(false); }}>⏻ ออกจากระบบ (Logout)</Btn>
          <Btn kind="dangerSoft" sm style={{ marginLeft: "auto" }} onClick={() => { if (confirm("ล้างข้อมูลทดลองทั้งหมด กลับเป็นข้อมูลตัวอย่าง?")) { dispatch({ type: "RESET" }); toast("รีเซ็ตข้อมูลตัวอย่างแล้ว", "info"); setSwitchOpen(false); } }}>↺ รีเซ็ตข้อมูลตัวอย่าง</Btn>
        </React.Fragment>}>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {st.users.map((u) => (
            <div key={u.id} className="ss-row" onClick={() => switchUser(u)} style={{ display: "flex", alignItems: "center", gap: 12, padding: "9px 12px", borderRadius: 12, cursor: "pointer", border: `1.5px solid ${u.id === user.id ? T.primary : T.border}`, background: u.id === user.id ? T.chipBg : T.surface }}>
              <Avatar name={u.name} img={u.img} size={38} />
              <div style={{ lineHeight: 1.35 }}>
                <div style={{ fontWeight: 700, fontSize: 13.5, color: T.text }}>{u.name}</div>
                <div style={{ fontSize: 11.5, color: T.sub }}>{st.roles[u.role].label} · {st.roles[u.role].allBranch ? "เห็นทุกสาขา" : branchOf(st, u.branch).name}</div>
              </div>
              {u.id === user.id && <span style={{ marginLeft: "auto", color: T.primary, fontWeight: 800, fontSize: 12 }}>✓ ใช้งานอยู่</span>}
            </div>
          ))}
        </div>
      </Modal>
    </div>
  );
}

function App() {
  return (
    <StoreProvider>
      <ToastProvider>
        <LoginGate>
          <Shell />
        </LoginGate>
      </ToastProvider>
    </StoreProvider>
  );
}

window.Shell = Shell;
window.App = App;
