// Reseller portal — Staff. The reseller's OWN company's teammates (see
// routes/portal-staff.ts) — entirely separate from Solo's internal
// admin_users (admin-staff-page.jsx). Confirmed with the customer:
// "keep this simple for now" + "this is customer staff only".
//
// Any signed-in reseller (member or company_admin) can VIEW the list;
// only a company_admin (or is_solo_staff "viewing as" this company) can
// invite or remove — matches routes/portal-staff.ts's
// companyAdminGateError exactly. A plain member sees a clean read-only
// list with no controls at all.
//
// v1 has no invite email (see backend header comment) — inviting a
// teammate creates a `pending` user row that lands in Solo staff's
// existing admin Users approval queue, exactly like a public signup.
//
// Reuses FieldBlock/DarkInput (reseller-login-page.jsx) and the same
// loadMe/handleSwitchCompany pattern as every other reseller page.

function ResellerStaffPage({ onNavigate }) {
  const [state, setState] = useState({ status: "loading", user: null, company: null, isSoloStaff: false });
  const [companies, setCompanies] = useState([]);
  const [staff, setStaff] = useState({ status: "loading", items: [], myUserId: null, myRole: "member" });
  const [showInvite, setShowInvite] = useState(false);
  const [busyId, setBusyId] = useState(null);

  const loadStaff = () => {
    fetch("/api/portal/staff", { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : { staff: [] }))
      .then((data) => setStaff({
        status: "ready", items: data.staff || [],
        myUserId: data.myUserId, myRole: data.myRole || "member",
      }))
      .catch(() => setStaff({ status: "ready", items: [], myUserId: null, myRole: "member" }));
  };

  const loadMe = (onDone) => {
    fetch("/api/portal/me", { credentials: "same-origin" })
      .then(async (r) => {
        if (!r.ok) throw new Error("not signed in");
        return r.json();
      })
      .then((data) => {
        setState({ status: "ready", user: data.user, company: data.company, isSoloStaff: !!data.isSoloStaff });
        if (data.isSoloStaff) {
          fetch("/api/portal/companies", { credentials: "same-origin" })
            .then((r) => (r.ok ? r.json() : { companies: [] }))
            .then((d) => setCompanies(d.companies || []))
            .catch(() => setCompanies([]));
        }
        if (onDone) onDone();
      })
      .catch(() => onNavigate("reseller-login"));
  };

  const handleSwitchCompany = (companyId) => {
    fetch("/api/portal/switch-company", {
      method: "POST", credentials: "same-origin",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ companyId }),
    })
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then(() => loadMe(loadStaff))
      .catch(() => { /* switch failed silently */ });
  };

  useEffect(() => {
    loadMe();
    loadStaff();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps -- mount-only

  const removeStaff = async (row) => {
    if (!window.confirm(`Remove ${row.name} from your team? Their access will be suspended.`)) return;
    setBusyId(row.id);
    try {
      const res = await fetch(`/api/portal/staff/${row.id}/remove`, { method: "POST", credentials: "same-origin" });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { window.alert(data.error || "Something went wrong."); return; }
      loadStaff();
    } finally { setBusyId(null); }
  };

  if (state.status === "loading") {
    return <section style={{ background: "var(--pt-bg)", minHeight: "calc(100vh - 88px)" }} />;
  }

  const { user, company, isSoloStaff } = state;
  const canManage = isSoloStaff || staff.myRole === "company_admin";

  return (
    <ResellerShell
      page="portal-staff" onNavigate={onNavigate}
      userName={user.name} companyName={company.name}
      isSoloStaff={isSoloStaff} companies={companies}
      currentCompanyId={company.id} onSwitchCompany={handleSwitchCompany}
      subtitle="Reseller portal"
      title="Staff."
      actions={canManage ? (
        <button
          type="button" onClick={() => setShowInvite(true)} data-testid="staff-invite-btn"
          style={{
            background: "var(--pt-accent-bg)", color: "var(--pt-accent-fg)",
            border: "1px solid var(--pt-accent-bg)", padding: "12px 20px", cursor: "pointer",
            fontFamily: "var(--font-body)", fontSize: 11.5, fontWeight: 500,
            letterSpacing: "0.14em", textTransform: "uppercase",
          }}
        >+ Invite teammate</button>
      ) : undefined}
    >
      <p style={{
        fontFamily: "var(--font-body)", fontSize: 14,
        color: "var(--pt-fg-dim)", margin: "-16px 0 36px",
      }}>
        {canManage
          ? "Manage who at your company can sign in to the portal."
          : "Your teammates with portal access. Only your company admin can invite or remove people."}
      </p>

      {staff.status === "loading" ? (
        <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "var(--pt-fg-faint2)" }}>Loading&hellip;</div>
      ) : staff.items.length === 0 ? (
        <div style={{
          background: "var(--pt-surface)", border: "1px solid var(--pt-border)",
          padding: "22px 24px", fontFamily: "var(--font-body)", fontSize: 13.5, color: "var(--pt-fg-dimmer)",
        }}>No teammates yet.</div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {staff.items.map((row) => (
            <StaffRow
              key={row.id} row={row} isSelf={row.id === staff.myUserId}
              canManage={canManage} busy={busyId === row.id}
              onRemove={() => removeStaff(row)}
            />
          ))}
        </div>
      )}

      {showInvite && (
        <InviteStaffModal
          onCancel={() => setShowInvite(false)}
          onInvited={() => { setShowInvite(false); loadStaff(); }}
        />
      )}
    </ResellerShell>
  );
}

function StaffRow({ row, isSelf, canManage, busy, onRemove }) {
  const roleLabel = row.role === "company_admin" ? "Company admin" : "Member";
  const suspended = row.status === "suspended";
  const pending = row.status === "pending";
  return (
    <div
      data-testid={`staff-row-${row.id}`}
      style={{
        display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, flexWrap: "wrap",
        background: "var(--pt-surface)", border: "1px solid var(--pt-border)",
        padding: "16px 20px", opacity: suspended ? 0.55 : 1,
      }}
    >
      <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
        <div style={{
          width: 36, height: 36, flexShrink: 0, borderRadius: "50%",
          display: "flex", alignItems: "center", justifyContent: "center",
          border: "1px solid var(--pt-border-strong)", color: "var(--pt-fg-3)",
        }}><IconStaff size={16} /></div>
        <div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 14.5, fontWeight: 600, color: "var(--pt-fg)" }}>
            {row.name}{isSelf && <span style={{ color: "var(--pt-fg-faint2)", fontWeight: 500 }}> (you)</span>}
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12.5, color: "var(--pt-fg-dim)", marginTop: 2 }}>
            {row.email} &middot; {roleLabel}
            {pending ? " \u00b7 Awaiting approval" : suspended ? " \u00b7 Suspended" : ""}
          </div>
        </div>
      </div>
      {canManage && !isSelf && !suspended && (
        <button
          type="button" disabled={busy} onClick={onRemove} data-testid={`staff-remove-${row.id}`}
          style={{
            background: "none", border: "1px solid var(--pt-error-border)", color: "var(--pt-error-text)",
            cursor: busy ? "not-allowed" : "pointer", padding: "8px 16px",
            fontFamily: "var(--font-body)", fontSize: 10.5, fontWeight: 500,
            letterSpacing: "0.1em", textTransform: "uppercase", opacity: busy ? 0.5 : 1,
          }}
        >Remove</button>
      )}
    </div>
  );
}

function InviteStaffModal({ onCancel, onInvited }) {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");

  const canSubmit = name.trim() && email.trim() && !busy;

  const submit = async (e) => {
    e.preventDefault();
    if (!canSubmit) return;
    setBusy(true); setError("");
    try {
      const res = await fetch("/api/portal/staff/invite", {
        method: "POST", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, email }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { setError(data.error || "Something went wrong."); setBusy(false); return; }
      onInvited();
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
      setBusy(false);
    }
  };

  return (
    <div style={{
      position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)",
      display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1000, padding: 20,
    }}>
      <div style={{
        background: "var(--pt-bg)", border: "1px solid var(--pt-border-strong)",
        padding: "32px 34px", maxWidth: 420, width: "100%",
      }}>
        <div style={{
          fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 20,
          textTransform: "uppercase", color: "var(--pt-fg)", marginBottom: 20,
        }}>Invite a teammate</div>

        {error && (
          <div style={{
            background: "var(--pt-error-bg)", border: "1px solid var(--pt-error-border)",
            color: "var(--pt-error-text)", padding: "12px 14px", marginBottom: 18,
            fontFamily: "var(--font-body)", fontSize: 13, lineHeight: 1.5,
          }}>{error}</div>
        )}

        <form onSubmit={submit}>
          <FieldBlock label="Name">
            <DarkInput required data-testid="staff-invite-name" value={name} onChange={(e) => setName(e.target.value)} />
          </FieldBlock>
          <FieldBlock label="Email" hint="They'll be able to set their own password once approved.">
            <DarkInput required type="email" data-testid="staff-invite-email" value={email} onChange={(e) => setEmail(e.target.value)} />
          </FieldBlock>
          <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 10 }}>
            <button type="button" onClick={onCancel} disabled={busy} style={{
              background: "none", border: "1px solid var(--pt-border-strong)", color: "var(--pt-fg-3)",
              padding: "12px 20px", cursor: "pointer", fontFamily: "var(--font-body)", fontSize: 11.5,
              fontWeight: 500, letterSpacing: "0.12em", textTransform: "uppercase",
            }}>Cancel</button>
            <button type="submit" disabled={!canSubmit} data-testid="staff-invite-submit" style={{
              background: canSubmit ? "var(--pt-accent-bg)" : "var(--pt-accent-bg-disabled)",
              color: canSubmit ? "var(--pt-accent-fg)" : "var(--pt-accent-fg-disabled)",
              border: `1px solid ${canSubmit ? "var(--pt-accent-bg)" : "var(--pt-accent-bg-disabled)"}`,
              padding: "12px 22px", cursor: canSubmit ? "pointer" : "not-allowed",
              fontFamily: "var(--font-body)", fontSize: 11.5, fontWeight: 500,
              letterSpacing: "0.12em", textTransform: "uppercase",
            }}>{busy ? "Sending\u2026" : "Send invite"}</button>
          </div>
        </form>
      </div>
    </div>
  );
}

Object.assign(window, { ResellerStaffPage });
