/* ============================================================
   Staff console shell (admin.* host) — login-gated.
   - Admins land on the dispatch board + roster.
   - Crew land on their personal board.
   State is loaded from the API and polled so the board stays live.
   ============================================================ */
function StaffApp() {
  const [phase, setPhase] = useState("loading"); // loading | login | ready
  const [user, setUser] = useState(null);        // { id, name, role }
  const [staff, setStaff] = useState({ employees: [], tickets: [] });
  const [adminOpenId, setAdminOpenId] = useState(null);
  const [empOpenId, setEmpOpenId] = useState(null);
  const [addEmp, setAddEmp] = useState(false);
  const [editEmpId, setEditEmpId] = useState(null);   // crew member being edited

  const reload = async () => {
    const s = await API.loadStaffState();
    setStaff(s);
    return s;
  };

  // Resume an existing session on load.
  useEffect(() => {
    (async () => {
      try {
        const me = await API.me();
        setUser(me.user);
        await reload();
        setPhase("ready");
      } catch (_e) {
        setPhase("login");
      }
    })();
  }, []);

  // Live updates while signed in.
  useEffect(() => {
    if (phase !== "ready") return;
    const t = setInterval(() => { reload().catch(() => {}); }, 15000);
    return () => clearInterval(t);
  }, [phase]);

  async function onLoggedIn(u) {
    setUser(u);
    await reload();
    setPhase("ready");
  }

  async function logout() {
    try { await API.logout(); } catch (_e) {}
    setUser(null); setStaff({ employees: [], tickets: [] });
    setAdminOpenId(null); setEmpOpenId(null);
    setPhase("login");
  }

  const actions = {
    async moveTicket(id, status) { await API.patchTicket(id, { status }); await reload(); },
    async assign(id, ids) { await API.patchTicket(id, { assigneeIds: ids }); await reload(); },
    async setPriority(id, p) { await API.patchTicket(id, { priority: p }); await reload(); },
    async addNote(id, text) { await API.addNote(id, text); await reload(); },
    addEmployee() { setAddEmp(true); },
    async createEmployee(payload) { await API.createEmployee(payload); await reload(); setAddEmp(false); },
    openEmployee(id) { setEditEmpId(id); },
    async saveEmployee(id, payload) { await API.updateEmployee(id, payload); await reload(); },
    async deleteEmployee(id) { await API.deleteEmployee(id); await reload(); setEditEmpId(null); },
    async setDispatcher(id, on) { await API.updateEmployee(id, { canDispatch: on }); await reload(); },
    async archiveEmployee(id) { await API.updateEmployee(id, { active: false }); await reload(); },
    async restoreEmployee(id) { await API.updateEmployee(id, { active: true }); await reload(); },
  };

  const editEmp = staff.employees.find((e) => e.id === editEmpId) || null;

  if (phase === "loading") {
    return <div style={{ height: "100vh", display: "flex", alignItems: "center", justifyContent: "center", color: "#9AA3A5", fontFamily: "var(--font-display)" }}>Loading…</div>;
  }
  if (phase === "login") {
    return <LoginView onLoggedIn={onLoggedIn} />;
  }

  // Dispatchers (admins + crew granted office access): dispatch board + roster.
  if (user.canDispatch) {
    return (
      <div style={{ display: "flex", flexDirection: "column", height: "100vh", overflow: "hidden" }}>
        <StaffTopBar user={user} onLogout={logout} />
        <div style={{ flex: 1, overflow: "hidden", position: "relative" }}>
          <AdminView state={staff} actions={actions} openId={adminOpenId} setOpenId={setAdminOpenId} user={user} />
        </div>
        <AddEmployeeModal open={addEmp} onClose={() => setAddEmp(false)} onCreate={actions.createEmployee} />
        <EditEmployeeModal emp={editEmp} onClose={() => setEditEmpId(null)} onSave={actions.saveEmployee} onDelete={actions.deleteEmployee} />
      </div>
    );
  }

  // Crew: personal board (its own header carries the sign-out).
  return (
    <div style={{ height: "100vh", overflow: "hidden" }}>
      <EmployeeBoard state={staff} actions={actions} employeeId={user.id} onLogout={logout} openId={empOpenId} setOpenId={setEmpOpenId} />
    </div>
  );
}

/* ---- Top bar (admin) ---- */
function StaffTopBar({ user, onLogout }) {
  const mobile = useIsMobile();
  return (
    <header style={{ height: 60, flexShrink: 0, background: "#fff", borderBottom: "1px solid #E6E6E6", display: "flex", alignItems: "center", justifyContent: "space-between", padding: mobile ? "0 14px" : "0 22px", zIndex: 50 }}>
      <BrandLockup tone="dark" iconColor="#2F6B3A" />
      <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
          <Avatar name={user.name} color="#16331E" size={32} />
          {!mobile && (
            <div style={{ lineHeight: 1.2 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: "#16331E" }}>{user.name}</div>
              <div style={{ fontSize: 11, color: "#9AA3A5" }}>{user.canDispatch && user.role !== "admin" ? "Office · Dispatcher" : "Camp Office"}</div>
            </div>
          )}
        </div>
        <Button kind="ghost" icon="log-out" size="sm" onClick={onLogout}>{mobile ? "" : "Sign out"}</Button>
      </div>
    </header>
  );
}

/* ---- Login (split panel) ---- */
function LoginView({ onLoggedIn }) {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const mobile = useIsMobile();

  async function submit() {
    if (busy) return;
    setError("");
    if (!username.trim() || !password) { setError("Enter your username and password."); return; }
    setBusy(true);
    try {
      const r = await API.login(username.trim(), password);
      await onLoggedIn(r.user);
    } catch (e) {
      setError(e.message || "Sign-in failed.");
      setBusy(false);
    }
  }

  const fld = { fontFamily: "inherit", fontSize: 15, padding: "0 14px", height: 50, width: "100%", boxSizing: "border-box", border: "1px solid #E6E6E6", borderRadius: 8, background: "#fff", color: "#16331E", outline: "none" };
  const lab = { fontFamily: "var(--font-sans)", fontWeight: 600, fontSize: 13, color: "#16331E", marginBottom: 6, display: "block" };

  return (
    <div style={{ display: "grid", gridTemplateColumns: mobile ? "1fr" : "minmax(0,420px) minmax(0,1fr)", height: "100vh" }}>
      <aside style={{ display: mobile ? "none" : "flex", background: "#16331E", color: "#fff", padding: "48px 44px", position: "relative", overflow: "hidden", flexDirection: "column" }}>
        <div style={{ position: "absolute", left: -70, top: -50, opacity: 0.06, pointerEvents: "none" }}><BrandMark size={360} color="#6FA07C" /></div>
        <div style={{ position: "relative", zIndex: 1 }}><BrandLockup tone="light" iconColor="#6FA07C" /></div>
        <div style={{ position: "relative", zIndex: 1, marginTop: "auto" }}>
          <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 38, lineHeight: 1.05, letterSpacing: "-0.025em" }}>Camp Office &amp; ranger crew sign-in.</div>
          <p style={{ marginTop: 16, fontSize: 16, lineHeight: 1.5, color: "rgba(255,255,255,0.7)", maxWidth: 320 }}>Dispatch, assign, and track every work order across the reservation. Crew see their own board.</p>
        </div>
      </aside>
      <main style={{ background: "#F2F2F2", display: "flex", flexDirection: "column", alignItems: "center", padding: mobile ? "32px 20px" : "48px 40px", overflowY: "auto", minHeight: 0 }}>
        <div style={{ width: "100%", maxWidth: 380, margin: "auto 0" }}>
          {mobile && <div style={{ marginBottom: 26 }}><BrandLockup tone="dark" iconColor="#2F6B3A" /></div>}
          <h2 style={{ margin: 0, fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 24, letterSpacing: "-0.02em", color: "#16331E" }}>Sign in</h2>
          <p style={{ margin: "5px 0 22px", fontSize: 14, color: "#515151" }}>Use the account the camp office set up for you.</p>
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            <div>
              <label style={lab}>Username</label>
              <input style={fld} value={username} autoFocus autoComplete="username"
                onChange={(e) => setUsername(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} placeholder="marcus" />
            </div>
            <div>
              <label style={lab}>Password</label>
              <input style={fld} type="password" value={password} autoComplete="current-password"
                onChange={(e) => setPassword(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} placeholder="••••••••" />
            </div>
            {error && <div style={{ display: "flex", alignItems: "center", gap: 6, color: "#FF5E2E", fontSize: 13, fontWeight: 500 }}><Icon name="alert-triangle" size={13} color="#FF5E2E" />{error}</div>}
            <Button kind="primary" iconRight="arrow-right" onClick={submit} disabled={busy} style={{ width: "100%" }}>{busy ? "Signing in…" : "Sign in"}</Button>
          </div>
        </div>
      </main>
    </div>
  );
}

/* ---- Add crew member (admin) — now also provisions a login ---- */
function AddEmployeeModal({ open, onClose, onCreate }) {
  const [f, setF] = useState({ name: "", trade: "", email: "", phone: "", username: "", password: "" });
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const mobile = useIsMobile();
  const twoCol = mobile ? "1fr" : "1fr 1fr";
  useEffect(() => { if (open) { setF({ name: "", trade: "", email: "", phone: "", username: "", password: "" }); setError(""); setBusy(false); } }, [open]);
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const valid = f.name.trim() && f.trade.trim() && f.username.trim() && f.password.length >= 6;
  const fld = { fontFamily: "inherit", fontSize: 15, padding: "0 14px", height: 48, width: "100%", boxSizing: "border-box", border: "1px solid #E6E6E6", borderRadius: 8, background: "#fff", color: "#16331E", outline: "none" };
  const lab = { fontFamily: "var(--font-sans)", fontWeight: 600, fontSize: 13, color: "#16331E", marginBottom: 6, display: "block" };

  async function create() {
    if (!valid || busy) return;
    setBusy(true); setError("");
    try {
      await onCreate({
        name: f.name.trim(), trade: f.trade.trim(),
        email: f.email.trim(), phone: f.phone.trim(),
        username: f.username.trim(), password: f.password,
      });
    } catch (e) {
      setError(e.message || "Could not create the account.");
      setBusy(false);
    }
  }

  return (
    <Modal open={open} onClose={onClose} width={460}>
      <div style={{ padding: 26 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}>
          <h2 style={{ margin: 0, fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 20, letterSpacing: "-0.02em", color: "#16331E" }}>Add crew member</h2>
          <button onClick={onClose} style={{ width: 32, height: 32, borderRadius: 8, border: "1px solid #E6E6E6", background: "#fff", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}><Icon name="x" size={15} color="#515151" /></button>
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div><label style={lab}>Full name *</label><input style={fld} value={f.name} onChange={(e) => set("name", e.target.value)} placeholder="Wade Carroll" /></div>
          <div><label style={lab}>Trade / specialty *</label><input style={fld} value={f.trade} onChange={(e) => set("trade", e.target.value)} placeholder="Buildings & Structures" /></div>
          <div style={{ display: "grid", gridTemplateColumns: twoCol, gap: 12 }}>
            <div><label style={lab}>Email</label><input style={fld} value={f.email} onChange={(e) => set("email", e.target.value)} placeholder="name@camp.org" /></div>
            <div><label style={lab}>Phone</label><input style={fld} value={f.phone} onChange={(e) => set("phone", e.target.value)} placeholder="(860) 555-0000" /></div>
          </div>
          <div style={{ height: 1, background: "#F2F2F2", margin: "2px 0" }}></div>
          <div style={{ display: "grid", gridTemplateColumns: twoCol, gap: 12 }}>
            <div><label style={lab}>Username *</label><input style={fld} value={f.username} autoComplete="off" onChange={(e) => set("username", e.target.value)} placeholder="wade" /></div>
            <div><label style={lab}>Temp password *</label><input style={fld} type="text" value={f.password} autoComplete="off" onChange={(e) => set("password", e.target.value)} placeholder="min 6 characters" /></div>
          </div>
          {error && <div style={{ display: "flex", alignItems: "center", gap: 6, color: "#FF5E2E", fontSize: 13, fontWeight: 500 }}><Icon name="alert-triangle" size={13} color="#FF5E2E" />{error}</div>}
        </div>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 22 }}>
          <Button kind="ghost" onClick={onClose}>Cancel</Button>
          <Button kind="primary" disabled={!valid || busy} onClick={create}>{busy ? "Adding…" : "Add to roster"}</Button>
        </div>
      </div>
    </Modal>
  );
}

/* ---- Edit crew member (admin) — full detail + privilege + remove ------- */
function EditEmployeeModal({ emp, onClose, onSave, onDelete }) {
  const mobile = useIsMobile();
  const [f, setF] = useState({ name: "", trade: "", email: "", phone: "", capacity: 6, canDispatch: false, password: "" });
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [confirmDelete, setConfirmDelete] = useState(false);

  useEffect(() => {
    if (emp) {
      setF({ name: emp.name || "", trade: emp.trade || "", email: emp.email === "—" ? "" : (emp.email || ""), phone: emp.phone === "—" ? "" : (emp.phone || ""), capacity: emp.capacity || 6, canDispatch: !!emp.canDispatch, password: "" });
      setError(""); setConfirmDelete(false); setBusy(false);
    }
  }, [emp && emp.id]);

  if (!emp) return null;
  const isAdmin = emp.role === "admin";
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const valid = f.name.trim() && f.trade.trim() && (f.password === "" || f.password.length >= 6);
  const twoCol = mobile ? "1fr" : "1fr 1fr";
  const fld = { fontFamily: "inherit", fontSize: 15, padding: "0 14px", height: 48, width: "100%", boxSizing: "border-box", border: "1px solid #E6E6E6", borderRadius: 8, background: "#fff", color: "#16331E", outline: "none" };
  const lab = { fontFamily: "var(--font-sans)", fontWeight: 600, fontSize: 13, color: "#16331E", marginBottom: 6, display: "block" };

  const run = (fn) => async () => { if (busy) return; setBusy(true); setError(""); try { await fn(); } catch (e) { setError(e.message || "Something went wrong."); } finally { setBusy(false); } };
  async function save() {
    const payload = { name: f.name.trim(), trade: f.trade.trim(), email: f.email.trim() || "—", phone: f.phone.trim() || "—", capacity: Number(f.capacity) || 6 };
    if (!isAdmin) payload.canDispatch = f.canDispatch; // admins always dispatch; privilege is locked
    if (f.password.length >= 6) payload.password = f.password;
    await onSave(emp.id, payload);
    onClose();
  }

  return (
    <Modal open={!!emp} onClose={onClose} width={480}>
      <div style={{ padding: mobile ? 20 : 26 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12, minWidth: 0 }}>
            <Avatar name={f.name || emp.name} color={emp.color} size={40} />
            <div style={{ minWidth: 0 }}>
              <h2 style={{ margin: 0, fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 19, letterSpacing: "-0.02em", color: "#16331E", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>Edit crew member</h2>
              {!emp.active && <span style={{ fontSize: 12, color: "#9AA3A5" }}>Archived</span>}
            </div>
          </div>
          <button onClick={onClose} style={{ width: 32, height: 32, borderRadius: 8, border: "1px solid #E6E6E6", background: "#fff", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}><Icon name="x" size={15} color="#515151" /></button>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div><label style={lab}>Full name *</label><input style={fld} value={f.name} onChange={(e) => set("name", e.target.value)} /></div>
          <div><label style={lab}>Trade / specialty *</label><input style={fld} value={f.trade} onChange={(e) => set("trade", e.target.value)} /></div>
          <div style={{ display: "grid", gridTemplateColumns: twoCol, gap: 12 }}>
            <div><label style={lab}>Email</label><input style={fld} value={f.email} onChange={(e) => set("email", e.target.value)} placeholder="name@camp.org" /></div>
            <div><label style={lab}>Phone</label><input style={fld} value={f.phone} onChange={(e) => set("phone", e.target.value)} placeholder="(860) 555-0000" /></div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: twoCol, gap: 12 }}>
            <div><label style={lab}>Daily capacity</label><input style={fld} type="number" min="1" max="20" value={f.capacity} onChange={(e) => set("capacity", e.target.value)} /></div>
            <div><label style={lab}>New password</label><input style={fld} type="text" value={f.password} autoComplete="off" onChange={(e) => set("password", e.target.value)} placeholder="leave blank to keep" /></div>
          </div>

          {/* Privilege */}
          <div>
            <label style={lab}>Privilege</label>
            {isAdmin ? (
              <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "12px 14px", borderRadius: 10, border: "1.5px solid #E6E6E6", background: "#FAFBFB", color: "#245730", fontSize: 14, fontWeight: 600 }}>
                <Icon name="shield" size={15} color="#245730" />Office admin — full access (can't be changed here)
              </div>
            ) : (
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
                {[
                  { on: false, t: "Crew", s: "Own board only" },
                  { on: true, t: "Office", s: "Can assign & run board" },
                ].map((opt) => {
                  const active = f.canDispatch === opt.on;
                  return (
                    <button key={opt.t} type="button" onClick={() => set("canDispatch", opt.on)} style={{
                      textAlign: "left", padding: "10px 12px", borderRadius: 10, cursor: "pointer",
                      border: "1.5px solid " + (active ? "#2F6B3A" : "#E6E6E6"), background: active ? "#E5F0E7" : "#fff",
                    }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 14, fontWeight: 700, color: active ? "#245730" : "#16331E" }}>
                        {opt.on && <Icon name="shield" size={13} color={active ? "#245730" : "#9AA3A5"} />}{opt.t}
                      </div>
                      <div style={{ fontSize: 11.5, color: "#515151", marginTop: 2 }}>{opt.s}</div>
                    </button>
                  );
                })}
              </div>
            )}
          </div>

          {error && <div style={{ display: "flex", alignItems: "center", gap: 6, color: "#FF5E2E", fontSize: 13, fontWeight: 500 }}><Icon name="alert-triangle" size={13} color="#FF5E2E" />{error}</div>}
        </div>

        {/* Footer: archive/restore + delete on the left, save on the right */}
        <div style={{ marginTop: 22, paddingTop: 16, borderTop: "1px solid #F2F2F2", display: "flex", flexDirection: mobile ? "column" : "row", gap: 10, alignItems: mobile ? "stretch" : "center" }}>
          {!isAdmin && (
            <div style={{ display: "flex", gap: 8 }}>
              {emp.active
                ? <Button kind="ghost" size="sm" icon="archive" disabled={busy} onClick={run(async () => { await onSave(emp.id, { active: false }); onClose(); })}>Archive</Button>
                : <Button kind="ghost" size="sm" icon="rotate-ccw" disabled={busy} onClick={run(async () => { await onSave(emp.id, { active: true }); onClose(); })}>Restore</Button>}
              {confirmDelete
                ? <Button kind="primary" size="sm" icon="trash" disabled={busy} onClick={run(() => onDelete(emp.id))} style={{ background: "#FF5E2E" }}>Delete forever?</Button>
                : <Button kind="ghost" size="sm" icon="trash" disabled={busy} onClick={() => setConfirmDelete(true)} style={{ color: "#FF5E2E" }}>Delete</Button>}
            </div>
          )}
          <div style={{ display: "flex", gap: 10, marginLeft: mobile ? 0 : "auto" }}>
            <Button kind="ghost" size="sm" onClick={onClose} style={{ flex: mobile ? 1 : "none" }}>Cancel</Button>
            <Button kind="primary" size="sm" disabled={!valid || busy} onClick={run(save)} style={{ flex: mobile ? 1 : "none" }}>{busy ? "Saving…" : "Save changes"}</Button>
          </div>
        </div>
      </div>
    </Modal>
  );
}

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