// App shell: Sidebar, Topbar, Breadcrumb, Toast system, Modal helpers

const { useState, useEffect, useRef, useMemo, useCallback, createContext, useContext } = React;

// ── Toast context ────────────────────────────────────────────
const ToastCtx = createContext(null);
function ToastProvider({ children }) {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((msg, kind = "info") => {
    const id = Math.random().toString(36).slice(2);
    setToasts((t) => [...t, { id, msg, kind }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 3500);
  }, []);
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="toast-wrap">
        {toasts.map((t) => (
          <div key={t.id} className="toast">
            <span style={{
              width: 8, height: 8, borderRadius: "50%",
              background: t.kind === "success" ? "var(--emerald)" : t.kind === "danger" ? "var(--rose)" : t.kind === "warn" ? "var(--amber)" : "var(--syk-blue-soft)"
            }} />
            <span>{t.msg}</span>
          </div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
}
const useToast = () => useContext(ToastCtx);

// ── Sidebar ──────────────────────────────────────────────────
function Sidebar({ active, onNav, collapsed, lang, onCollapse, onCloseMobile, mobileOpen }) {
  const T = (it) => lang === "th" ? it.th : it.en;
  const wrap = {
    position: "sticky",
    top: 0,
    height: "100vh",
    overflowY: "auto",
    background: "var(--glass)",
    borderRight: "1px solid var(--line)",
    backdropFilter: "blur(24px) saturate(140%)",
    WebkitBackdropFilter: "blur(24px) saturate(140%)",
    padding: "18px 14px",
    display: "flex", flexDirection: "column", gap: 4,
    zIndex: 30,
  };
  const mobile = {
    position: "fixed", inset: "0 auto 0 0",
    width: 280, transform: mobileOpen ? "translateX(0)" : "translateX(-100%)",
    transition: "transform .28s cubic-bezier(.2,.7,.2,1)",
    boxShadow: mobileOpen ? "0 20px 60px rgba(0,0,0,0.5)" : "none",
    background: "var(--bg-1)",
  };
  const isMobile = typeof window !== "undefined" && window.innerWidth <= 900;
  const style = isMobile ? { ...wrap, ...mobile } : wrap;

  return (
    <>
      {isMobile && mobileOpen && (
        <div onClick={onCloseMobile} style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)", zIndex: 25 }} />
      )}
      <aside style={style}>
        {/* Logo */}
        <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "4px 6px 18px", borderBottom: "1px solid var(--line)", marginBottom: 12 }}>
          <div style={{
            width: 44, height: 44, borderRadius: 12, flexShrink: 0,
            background: "#1a2670",
            display: "flex", alignItems: "center", justifyContent: "center",
            overflow: "hidden",
            boxShadow: "0 6px 22px -6px rgba(40,72,255,0.55), 0 1px 0 rgba(255,255,255,0.08) inset",
          }}>
            <img
              src="assets/syk-logo.svg"
              onError={(e) => {
                e.target.onerror = null;
                e.target.src = e.target.src.endsWith('.svg') ? 'assets/syk-logo.png' :
                               e.target.src.endsWith('.png') ? 'assets/syk-logo.jpg' : '';
              }}
              alt="SYK"
              style={{ width: "100%", height: "100%", objectFit: "cover" }}
            />
          </div>
          {!collapsed && (
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 14, letterSpacing: "-0.01em" }}>SYK Construction</div>
              <div style={{ fontSize: 10.5, color: "var(--ink-mute)", textTransform: "uppercase", letterSpacing: "0.1em", fontWeight: 500 }}>Document System</div>
            </div>
          )}
        </div>

        {/* Nav */}
        <nav style={{ display: "flex", flexDirection: "column", gap: 2 }}>
          {NAV.map((item) => {
            const Icon = I[item.icon] || I.dot;
            const isActive = active === item.id;
            return (
              <button key={item.id} onClick={() => {
                  // Guard: confirm if there are unsaved changes
                  if (window.__confirmLeave && !window.__confirmLeave(`ต้องการเปลี่ยนไปที่ "${T(item)}"?`)) return;
                  onNav(item.id); onCloseMobile?.();
                }} title={collapsed ? T(item) : ""}
                style={{
                  display: "flex", alignItems: "center", gap: 12,
                  padding: collapsed ? "10px 12px" : "10px 12px",
                  background: isActive ? "linear-gradient(90deg, rgba(40,72,255,0.18), rgba(40,72,255,0.04))" : "transparent",
                  border: 0,
                  borderLeft: isActive ? "2px solid var(--syk-blue-soft)" : "2px solid transparent",
                  color: isActive ? "var(--ink)" : "var(--ink-soft)",
                  borderRadius: 10,
                  cursor: "pointer", textAlign: "left",
                  fontSize: 13, fontWeight: isActive ? 600 : 500,
                  transition: "all .18s",
                  position: "relative", justifyContent: collapsed ? "center" : "flex-start",
                }}
                onMouseEnter={(e) => !isActive && (e.currentTarget.style.background = "var(--glass-2)")}
                onMouseLeave={(e) => !isActive && (e.currentTarget.style.background = "transparent")}
              >
                <span style={{ color: isActive ? "var(--syk-blue-soft)" : "var(--ink-mute)", display: "inline-flex" }}><Icon /></span>
                {!collapsed && <span>{T(item)}</span>}
                {isActive && !collapsed && <span style={{ marginLeft: "auto", width: 4, height: 4, borderRadius: "50%", background: "var(--syk-blue-soft)", boxShadow: "0 0 8px var(--syk-blue-soft)" }} />}
              </button>
            );
          })}
        </nav>

        {/* Footer */}
        <div style={{ marginTop: "auto", paddingTop: 14, borderTop: "1px solid var(--line)" }}>
          {!collapsed && (
            <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 6px" }}>
              <div className="ava">นภ</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 12, fontWeight: 600 }}>คุณนภา (Admin)</div>
                <div style={{ fontSize: 10.5, color: "var(--ink-mute)" }}>นภา · จัดซื้อ/บัญชี</div>
              </div>
            </div>
          )}
          <button onClick={onCollapse} className="btn btn-ghost btn-sm desk-only" style={{ width: "100%", justifyContent: "center", marginTop: 6 }}>
            <I.chev dir={collapsed ? "right" : "left"} />
            {!collapsed && <span>ย่อแถบ</span>}
          </button>
        </div>
      </aside>
    </>
  );
}

// ── Topbar ───────────────────────────────────────────────────
function Topbar({ active, lang, onLang, onSearch, onOpenMobile, dark, onTheme }) {
  const item = NAV.find(n => n.id === active) || NAV[0];
  return (
    <header style={{
      position: "sticky", top: 0, zIndex: 20,
      background: "color-mix(in oklab, var(--bg-0) 70%, transparent)",
      backdropFilter: "blur(16px)", WebkitBackdropFilter: "blur(16px)",
      borderBottom: "1px solid var(--line)",
      padding: "12px 24px",
      display: "flex", alignItems: "center", gap: 16,
    }}>
      <button className="btn btn-ghost btn-sm mobile-only" onClick={onOpenMobile} style={{ width: 36, justifyContent: "center", padding: 0 }}>
        <I.menu />
      </button>

      {/* Breadcrumb */}
      <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "var(--ink-mute)" }}>
        <span>SYK</span>
        <I.chev size={12} />
        <span style={{ color: "var(--ink)" }}>{lang === "th" ? item.th : item.en}</span>
      </div>

      {/* Search */}
      <div style={{ marginLeft: "auto", flex: "0 1 360px", position: "relative" }} className="desk-only">
        <span style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)", color: "var(--ink-mute)" }}><I.search /></span>
        <input className="field" placeholder={lang === "th" ? "ค้นหาเอกสาร โครงการ วัสดุ…" : "Search documents, projects, materials…"}
               onChange={(e) => onSearch?.(e.target.value)}
               style={{ paddingLeft: 36, height: 36 }} />
        <span style={{ position: "absolute", right: 10, top: "50%", transform: "translateY(-50%)", color: "var(--ink-mute)", fontSize: 11, padding: "2px 6px", borderRadius: 6, background: "var(--glass-2)", border: "1px solid var(--line)" }}>⌘K</span>
      </div>

      {/* Lang */}
      <div style={{ display: "flex", background: "var(--glass)", border: "1px solid var(--line)", borderRadius: 8, padding: 2 }}>
        {["th", "en"].map((l) => (
          <button key={l} onClick={() => onLang(l)}
            style={{
              padding: "5px 10px", borderRadius: 6, border: 0, cursor: "pointer",
              background: lang === l ? "var(--glass-3)" : "transparent",
              color: lang === l ? "var(--ink)" : "var(--ink-mute)",
              fontSize: 11, fontWeight: 600, letterSpacing: "0.04em", textTransform: "uppercase"
            }}>{l}</button>
        ))}
      </div>

      <button className="btn btn-ghost btn-sm" onClick={onTheme} style={{ width: 36, justifyContent: "center", padding: 0 }} title="Toggle theme">
        {dark ? <I.sun /> : <I.moon />}
      </button>

      <button className="btn btn-ghost btn-sm" style={{ width: 36, justifyContent: "center", padding: 0, position: "relative" }}>
        <I.bell />
        <span style={{ position: "absolute", top: 4, right: 4, width: 7, height: 7, borderRadius: "50%", background: "var(--rose)", boxShadow: "0 0 0 2px var(--bg-0)" }} />
      </button>

      <UserMenu />
    </header>
  );
}

// User dropdown — shows current user + logout (web mode)
function UserMenu() {
  const [open, setOpen] = useState(false);
  const user = window.api?.getCurrentUser?.() || null;
  const initials = user
    ? (user.displayName || user.email || '?').substring(0, 2).toUpperCase()
    : 'นภ';
  const handleLogout = async () => {
    if (!confirm('ออกจากระบบ?')) return;
    if (window.api?.logout) {
      await window.api.logout();
      window.location.reload();
    }
  };
  return (
    <div className="desk-only" style={{ position: "relative" }}>
      <div className="ava" style={{ width: 32, height: 32, cursor: "pointer" }} onClick={() => setOpen(o => !o)}>
        {initials}
      </div>
      {open && (
        <>
          <div onClick={() => setOpen(false)} style={{ position: "fixed", inset: 0, zIndex: 99 }} />
          <div style={{
            position: "absolute", top: "calc(100% + 8px)", right: 0, zIndex: 100,
            background: "var(--bg-1)", border: "1px solid var(--line-strong)", borderRadius: 12,
            boxShadow: "0 20px 50px rgba(0,0,0,0.4)", minWidth: 240, padding: 8,
            backdropFilter: "blur(20px)", WebkitBackdropFilter: "blur(20px)",
          }}>
            {user ? (
              <>
                <div style={{ padding: "10px 12px", borderBottom: "1px solid var(--line)" }}>
                  <div style={{ fontSize: 12, fontWeight: 600 }}>{user.displayName || '—'}</div>
                  <div style={{ fontSize: 10.5, color: "var(--ink-mute)", marginTop: 2 }}>{user.email}</div>
                  <div style={{ marginTop: 6, display: "inline-block", padding: "2px 8px", borderRadius: 4,
                                background: "var(--glass-2)", fontSize: 9.5, color: "var(--syk-blue-soft)",
                                fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.08em" }}>
                    {user.role}
                  </div>
                </div>
                <button onClick={handleLogout}
                  style={{ width: "100%", textAlign: "left", padding: "10px 12px", background: "transparent",
                           border: 0, cursor: "pointer", color: "var(--rose)", fontSize: 12.5, borderRadius: 6,
                           display: "flex", alignItems: "center", gap: 8 }}
                  onMouseEnter={(e) => e.currentTarget.style.background = "rgba(255,107,138,0.1)"}
                  onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}>
                  🚪 ออกจากระบบ
                </button>
              </>
            ) : (
              <div style={{ padding: 12, fontSize: 11.5, color: "var(--ink-mute)" }}>
                💻 Desktop mode (Electron)
              </div>
            )}
          </div>
        </>
      )}
    </div>
  );
}

// ── Section header ────────────────────────────────────────────
function PageHeader({ title, subtitle, actions }) {
  return (
    <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 16, marginBottom: 20, flexWrap: "wrap" }}>
      <div>
        <h1 className="h1">{title}</h1>
        {subtitle && <p style={{ margin: "6px 0 0", color: "var(--ink-mute)", fontSize: 13 }}>{subtitle}</p>}
      </div>
      {actions && <div style={{ display: "flex", gap: 8, alignItems: "center" }}>{actions}</div>}
    </div>
  );
}

// ── Stat card ────────────────────────────────────────────────
function StatCard({ label, value, delta, hint, accent, icon }) {
  const Icon = I[icon] || null;
  return (
    <div className="card card-tight" style={{ position: "relative", overflow: "hidden" }}>
      <div style={{ position: "absolute", inset: 0, background: `radial-gradient(400px 200px at 100% 0%, ${accent || "rgba(40,72,255,0.18)"}, transparent 60%)`, pointerEvents: "none" }} />
      <div style={{ position: "relative", display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12 }}>
        <div>
          <div className="micro">{label}</div>
          <div className="mono" style={{ fontSize: 26, fontWeight: 700, marginTop: 6, letterSpacing: "-0.01em" }}>{value}</div>
          {delta != null && (
            <div style={{ marginTop: 6, fontSize: 12, color: delta >= 0 ? "var(--emerald)" : "var(--rose)", fontWeight: 500 }}>
              {delta >= 0 ? "▲" : "▼"} {Math.abs(delta)}% <span className="ink-mute" style={{ fontWeight: 400 }}>vs last month</span>
            </div>
          )}
          {hint && <div className="ink-mute" style={{ marginTop: 6, fontSize: 11.5 }}>{hint}</div>}
        </div>
        {Icon && (
          <div style={{
            width: 36, height: 36, borderRadius: 10,
            background: "var(--glass-2)", border: "1px solid var(--line)",
            display: "flex", alignItems: "center", justifyContent: "center",
            color: "var(--syk-blue-soft)",
          }}>
            <Icon size={18} />
          </div>
        )}
      </div>
    </div>
  );
}

// ── Status badge ─────────────────────────────────────────────
function StatusBadge({ status }) {
  const map = {
    active:    { c: "success", l: "ดำเนินการ"  },
    done:      { c: "info",    l: "เสร็จสิ้น"   },
    closing:   { c: "warn",    l: "ใกล้ปิดงาน" },
    paid:      { c: "success", l: "จ่ายแล้ว"    },
    issued:    { c: "info",    l: "ออกแล้ว"     },
    draft:     { c: "",        l: "ร่าง"        },
    pending:   { c: "warn",    l: "รออนุมัติ"   },
    approved:  { c: "success", l: "อนุมัติแล้ว" },
    sent:      { c: "info",    l: "ส่งแล้ว"     },
    received:  { c: "success", l: "รับของแล้ว" },
    rejected:  { c: "danger",  l: "ปฏิเสธ"      },
    billed:    { c: "gold",    l: "วางบิลแล้ว"  },
    ongoing:   { c: "info",    l: "กำลังทำ"     },
    planned:   { c: "",        l: "วางแผน"      },
  };
  const s = map[status] || { c: "", l: status };
  return <span className={`chip ${s.c}`}><span className="chip-dot" />{s.l}</span>;
}

Object.assign(window, { ToastProvider, useToast, Sidebar, Topbar, PageHeader, StatCard, StatusBadge, ProjectFilter, useSort, SortTH });

// ── Project filter dropdown (used across pages) ──────────────
function ProjectFilter({ value, onChange, lang, includeAll = true }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
      <span style={{ fontSize: 11.5, color: "var(--ink-mute)" }}>{lang === "th" ? "โครงการ:" : "Project:"}</span>
      <select className="field" value={value} onChange={(e) => onChange(e.target.value)} style={{ width: "auto", height: 34, fontSize: 12.5 }}>
        {includeAll && <option value="all">{lang === "th" ? "ทุกโครงการ" : "All projects"}</option>}
        {PROJECTS.map((p) => (
          <option key={p.code} value={p.code}>{p.code} · {p.name.length > 30 ? p.name.slice(0, 30) + "…" : p.name}</option>
        ))}
      </select>
    </div>
  );
}

// ── Sortable hook ─────────────────────────────────────────────
function useSort(rows, initialKey, initialDir = "asc") {
  const [key, setKey] = useState(initialKey);
  const [dir, setDir] = useState(initialDir);
  const sorted = useMemo(() => {
    if (!key) return rows;
    const arr = [...rows];
    arr.sort((a, b) => {
      const av = a[key], bv = b[key];
      if (av == null) return 1; if (bv == null) return -1;
      if (typeof av === "number" && typeof bv === "number") return dir === "asc" ? av - bv : bv - av;
      return dir === "asc" ? String(av).localeCompare(String(bv), "th") : String(bv).localeCompare(String(av), "th");
    });
    return arr;
  }, [rows, key, dir]);
  const toggle = (k) => {
    if (key === k) setDir(d => d === "asc" ? "desc" : "asc");
    else { setKey(k); setDir("asc"); }
  };
  return { sorted, key, dir, toggle };
}

function SortTH({ label, k, sort, align }) {
  const active = sort.key === k;
  return (
    <th onClick={() => sort.toggle(k)} style={{ cursor: "pointer", userSelect: "none", textAlign: align || "left" }}>
      <span style={{ display: "inline-flex", alignItems: "center", gap: 4, color: active ? "var(--ink)" : "var(--ink-mute)" }}>
        {label}
        <span style={{ fontSize: 9, opacity: active ? 1 : 0.4, transform: active && sort.dir === "desc" ? "rotate(180deg)" : "none", transition: "transform .15s" }}>▲</span>
      </span>
    </th>
  );
}
