// Solo staff admin area — Support Tickets: view, reply to, and manage
// the status of every support ticket raised by resellers inside the
// portal (see site/support-page.jsx for the reseller-facing raise/view
// flow, and routes/portal.ts / routes/admin-tickets.ts for the backend).
// Reached via the sidebar nav in AdminShell (see admin-shell.jsx). Reuses
// MiniField/ActionButton/SectionLabel/EmptyNote/ModalError/adminInputStyle/
// adminSelectStyle from admin-assets-page.jsx (loaded earlier — see
// index.html), same pattern as admin-orders-page.jsx.

const TICKET_STATUS_LABELS_UI = { open: "Open", in_progress: "In Progress", resolved: "Resolved", closed: "Closed" };
const TICKET_STATUS_COLORS = {
  open: "rgba(180,110,0,0.95)",
  in_progress: "rgba(30,110,190,0.95)",
  resolved: "rgba(20,140,60,0.95)",
  closed: "rgba(0,0,0,0.55)",
};
const TICKET_STATUS_FLOW = ["open", "in_progress", "resolved", "closed"];

function AdminTicketsPage({ onNavigate }) {
  const [state, setState] = useState({ status: "loading", admin: null, tickets: [], companies: [] });
  const [companyFilter, setCompanyFilter] = useState("");
  const [statusFilter, setStatusFilter] = useState("");
  const [openId, setOpenId] = useState(null);

  const load = () => {
    const params = new URLSearchParams();
    if (companyFilter) params.set("companyId", companyFilter);
    if (statusFilter) params.set("status", statusFilter);
    Promise.all([
      fetch("/api/admin/me", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
      fetch(`/api/admin/tickets?${params.toString()}`, { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
      fetch("/api/admin/companies", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
    ])
      .then(([me, tickets, companies]) => {
        setState({
          status: "ready", admin: me.admin,
          tickets: tickets.tickets || [], companies: companies.companies || [],
        });
      })
      .catch(() => onNavigate("admin-login"));
  };

  useEffect(load, [companyFilter, statusFilter]); // eslint-disable-line react-hooks/exhaustive-deps

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

  const isReadOnly = state.admin && state.admin.role !== "super_admin";

  return (
    <AdminShell admin={state.admin} page="admin-tickets" onNavigate={onNavigate}
      subtitle="Staff only" title="Support tickets.">
      <div style={{ display: "flex", gap: 12, flexWrap: "wrap", marginBottom: 24 }}>
        <MiniField label="Customer">
          <select value={companyFilter} onChange={(e) => setCompanyFilter(e.target.value)} style={adminSelectStyle}>
            <option value="">All customers</option>
            {state.companies.map((co) => <option key={co.id} value={co.id}>{co.name}</option>)}
          </select>
        </MiniField>
        <MiniField label="Status">
          <select value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)} style={adminSelectStyle}>
            <option value="">All statuses</option>
            {TICKET_STATUS_FLOW.map((s) => <option key={s} value={s}>{TICKET_STATUS_LABELS_UI[s]}</option>)}
          </select>
        </MiniField>
      </div>

      <SectionLabel>Tickets ({state.tickets.length})</SectionLabel>
      {state.tickets.length === 0 ? (
        <EmptyNote>No support tickets raised yet.</EmptyNote>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {state.tickets.map((t) => (
            <TicketRow
              key={t.id} ticket={t}
              open={openId === t.id}
              isReadOnly={isReadOnly}
              onToggle={() => setOpenId(openId === t.id ? null : t.id)}
              onSaved={load}
            />
          ))}
        </div>
      )}
    </AdminShell>
  );
}

function TicketRow({ ticket, open, isReadOnly, onToggle, onSaved }) {
  return (
    <div data-testid={`ticket-row-${ticket.id}`} style={{
      background: "rgba(0,0,0,0.02)", border: "1px solid rgba(0,0,0,0.14)",
    }}>
      <button
        type="button" onClick={onToggle} data-testid={`ticket-toggle-${ticket.id}`}
        style={{
          width: "100%", background: "none", border: "none", cursor: "pointer",
          padding: "16px 20px", display: "flex", justifyContent: "space-between",
          alignItems: "center", flexWrap: "wrap", gap: 12, textAlign: "left",
        }}>
        <div>
          <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 15, textTransform: "uppercase", color: "#000" }}>
            {ticket.ticket_number} <span style={{ color: "rgba(0,0,0,0.55)", fontSize: 12, fontWeight: 400 }}>· {ticket.company_name}</span>
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.55)", marginTop: 4 }}>
            <span style={{ color: TICKET_STATUS_COLORS[ticket.status] || "rgba(0,0,0,0.55)", textTransform: "uppercase", letterSpacing: "0.08em", fontSize: 11 }}>
              {TICKET_STATUS_LABELS_UI[ticket.status] || ticket.status}
            </span>
            {" · "}{ticket.severity} · {ticket.ticket_type}
            {" · "}{ticket.message_count} repl{ticket.message_count === 1 ? "y" : "ies"}
          </div>
        </div>
        <span style={{ fontFamily: "var(--font-body)", fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.55)" }}>
          {open ? "Close ↑" : "View →"}
        </span>
      </button>
      {open && <TicketDetail ticketId={ticket.id} isReadOnly={isReadOnly} onSaved={onSaved} />}
    </div>
  );
}

function TicketDetail({ ticketId, isReadOnly, onSaved }) {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);
  const [reply, setReply] = useState("");

  const load = () => {
    fetch(`/api/admin/tickets/${ticketId}`, { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then((d) => setData(d))
      .catch(() => setError("Couldn't load this ticket."));
  };

  useEffect(load, [ticketId]); // eslint-disable-line react-hooks/exhaustive-deps

  if (!data) {
    return (
      <div style={{ borderTop: "1px solid rgba(0,0,0,0.14)", padding: "20px" }}>
        {error ? <ModalError>{error}</ModalError> : <EmptyNote>Loading…</EmptyNote>}
      </div>
    );
  }

  const { ticket, messages } = data;

  const changeStatus = async (next) => {
    setBusy(true);
    setError("");
    try {
      const res = await fetch(`/api/admin/tickets/${ticketId}`, {
        method: "PATCH", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ status: next }),
      });
      const d = await res.json().catch(() => ({}));
      if (!res.ok) { setError(d.error || "Something went wrong."); setBusy(false); return; }
      load();
      onSaved();
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
    } finally {
      setBusy(false);
    }
  };

  const sendReply = async () => {
    if (!reply.trim()) return;
    setBusy(true);
    setError("");
    try {
      const res = await fetch(`/api/admin/tickets/${ticketId}/messages`, {
        method: "POST", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ body: reply.trim() }),
      });
      const d = await res.json().catch(() => ({}));
      if (!res.ok) { setError(d.error || "Something went wrong."); setBusy(false); return; }
      setReply("");
      load();
      onSaved();
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{ borderTop: "1px solid rgba(0,0,0,0.14)", padding: "20px" }}>
      {error && <ModalError>{error}</ModalError>}

      <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 18 }}>
        {TICKET_STATUS_FLOW.map((s) => (
          <button
            key={s} type="button" disabled={busy || ticket.status === s || isReadOnly}
            onClick={isReadOnly ? undefined : () => changeStatus(s)}
            data-testid={`ticket-status-${s}-${ticketId}`}
            title={isReadOnly ? "Master admins only — you have read-only access" : undefined}
            style={{
              background: ticket.status === s ? "#000" : "none",
              color: ticket.status === s ? "#fff" : "rgba(0,0,0,0.65)",
              border: `1px solid ${ticket.status === s ? "#000" : "rgba(0,0,0,0.3)"}`,
              padding: "7px 14px",
              cursor: isReadOnly ? "not-allowed" : ticket.status === s ? "default" : "pointer",
              opacity: busy || isReadOnly ? 0.6 : 1,
              fontFamily: "var(--font-body)", fontSize: 11, fontWeight: 500,
              letterSpacing: "0.08em", textTransform: "uppercase",
            }}>
            {TICKET_STATUS_LABELS_UI[s]}
          </button>
        ))}
      </div>

      <div style={{ display: "grid", gap: 14, gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", marginBottom: 20 }}>
        <DetailField label="Raised by">{ticket.name} ({ticket.email})</DetailField>
        <DetailField label="Phone">{ticket.phone || "—"}</DetailField>
        <DetailField label="Region">{ticket.region || "—"}</DetailField>
        <DetailField label="Asset / unit">
          {ticket.asset_serial_number
            ? `${ticket.asset_product_name} · ${ticket.asset_serial_number}`
            : "— Not unit-specific —"}
        </DetailField>
      </div>
      <div style={{ marginBottom: 24 }}>
        <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.24em", textTransform: "uppercase", color: "rgba(180,110,0,0.95)", fontWeight: 500, marginBottom: 8 }}>
          Description
        </div>
        <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", lineHeight: 1.6, whiteSpace: "pre-wrap" }}>
          {ticket.description}
        </div>
      </div>

      <div style={{ height: 1, background: "rgba(0,0,0,0.1)", margin: "18px 0" }} />
      <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.24em", textTransform: "uppercase", color: "rgba(180,110,0,0.95)", fontWeight: 500, marginBottom: 12 }}>
        Conversation ({messages.length})
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 10, marginBottom: 20 }}>
        {messages.length === 0 && <EmptyNote>No replies yet.</EmptyNote>}
        {messages.map((m) => (
          <div key={m.id} style={{
            padding: "12px 14px",
            background: m.author_type === "admin" ? "rgba(180,110,0,0.06)" : "rgba(0,0,0,0.02)",
            border: `1px solid ${m.author_type === "admin" ? "rgba(180,110,0,0.3)" : "rgba(0,0,0,0.1)"}`,
          }}>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)", marginBottom: 6 }}>
              {m.author_type === "admin" ? `Solo staff${m.admin_name ? ` · ${m.admin_name}` : ""}` : `Reseller${m.reseller_name ? ` · ${m.reseller_name}` : ""}`}
              {" · "}{m.created_at}
            </div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", lineHeight: 1.55, whiteSpace: "pre-wrap" }}>{m.body}</div>
          </div>
        ))}
      </div>

      <MiniField label="Reply to reseller">
        <textarea value={reply} onChange={(e) => setReply(e.target.value)} rows={3} style={{ ...adminInputStyle, resize: "vertical" }} />
      </MiniField>
      <ActionButton onClick={sendReply} disabled={busy || !reply.trim()} readOnly={isReadOnly} testId={`send-reply-${ticketId}`}>
        {busy ? "Sending…" : "Send reply"}
      </ActionButton>
    </div>
  );
}

function DetailField({ label, children }) {
  return (
    <div>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 9.5, letterSpacing: "0.16em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)", marginBottom: 6 }}>
        {label}
      </div>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{children}</div>
    </div>
  );
}

Object.assign(window, { AdminTicketsPage });
