// Solo staff admin area — Quotes: reseller/partner-created quotes,
// viewed and actioned here (Accept / Request PO / Reject) — never
// created here. Reached via the sidebar nav in AdminShell (see
// admin-shell.jsx). Reuses ModalError/SectionLabel/EmptyNote/MiniField/
// ActionButton/adminInputStyle/adminSelectStyle from admin-assets-page.jsx
// (loaded earlier — see index.html), and XeroSyncBadge-style pattern from
// admin-orders-page.jsx for the eventual linked Order's own sync badge.
//
// Quotes are always created in the RESELLER's OWN portal (see
// reseller-portal-dashboard.jsx's "New Quote" flow / portal.ts's POST
// /quotes) — admin only ever views them here and drives the
// submitted -> po_requested -> accepted|rejected flow. Accepting
// converts the quote into an Order and best-effort pushes it to
// Xero (Draft Quote) or QuickBooks (Estimate) depending on the
// company's region — see routes/admin-quotes.ts's /accept.

const QUOTE_STATUS_LABELS_UI = { submitted: "Submitted", po_requested: "PO Requested", accepted: "Accepted", rejected: "Rejected" };
const QUOTE_STATUS_COLORS = {
  submitted: "rgba(30,110,190,0.95)",
  po_requested: "rgba(180,110,0,0.95)",
  accepted: "rgba(20,140,60,0.95)",
  rejected: "rgba(190,40,40,0.9)",
};
const QUOTE_TAX_TREATMENT_LABELS = { standard: "Standard", export_no_tax: "Export — No Tax" };

function money(amount, currency) {
  const symbols = { GBP: "£", USD: "$", EUR: "€" };
  return `${symbols[currency] || ""}${Number(amount).toFixed(2)}`;
}

function AdminQuotesPage({ onNavigate }) {
  const [state, setState] = useState({ status: "loading", admin: null, quotes: [], companies: [], statuses: [] });
  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/quotes?${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, quotes, companies]) => {
        setState({
          status: "ready", admin: me.admin,
          quotes: quotes.quotes || [], statuses: quotes.statuses || [],
          companies: companies.companies || [],
        });
      })
      .catch(() => onNavigate("admin-login"));
  };

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

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

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

  return (
    <AdminShell admin={state.admin} page="admin-quotes" onNavigate={onNavigate}
      subtitle="Staff only — created by resellers, actioned here" title="Quotes.">
      <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>
            {(state.statuses.length ? state.statuses : ["submitted", "po_requested", "accepted", "rejected"]).map((s) => (
              <option key={s} value={s}>{QUOTE_STATUS_LABELS_UI[s] || s}</option>
            ))}
          </select>
        </MiniField>
      </div>

      <SectionLabel>Quotes ({state.quotes.length})</SectionLabel>
      {state.quotes.length === 0 ? (
        <EmptyNote>No quotes submitted by resellers yet.</EmptyNote>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {state.quotes.map((q) => (
            <QuoteRow
              key={q.id} quote={q}
              open={openId === q.id} isReadOnly={isReadOnly}
              onToggle={() => setOpenId(openId === q.id ? null : q.id)}
              onSaved={load} onNavigate={onNavigate}
            />
          ))}
        </div>
      )}
    </AdminShell>
  );
}

function QuoteRow({ quote, open, isReadOnly, onToggle, onSaved, onNavigate }) {
  return (
    <div data-testid={`quote-row-${quote.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={`quote-toggle-${quote.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" }}>
            {quote.quote_number} <span style={{ color: "rgba(0,0,0,0.55)", fontSize: 12, fontWeight: 400 }}>· {quote.company_name}</span>
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.55)", marginTop: 4 }}>
            <span style={{ color: QUOTE_STATUS_COLORS[quote.status] || "rgba(0,0,0,0.55)", textTransform: "uppercase", letterSpacing: "0.08em", fontSize: 11 }}>
              {QUOTE_STATUS_LABELS_UI[quote.status] || quote.status}
            </span>
            {" · "}{money(quote.subtotal, quote.currency)}
            {quote.po_number && <> · PO {quote.po_number}</>}
            {quote.created_by_name && <> · by {quote.created_by_name}</>}
          </div>
        </div>
        <span style={{ fontFamily: "var(--font-body)", fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.55)" }}>
          {open ? "Close ↑" : "Review →"}
        </span>
      </button>
      {open && <QuoteDetail quoteId={quote.id} isReadOnly={isReadOnly} onSaved={onSaved} onNavigate={onNavigate} />}
    </div>
  );
}

function QuoteDetail({ quoteId, isReadOnly, onSaved, onNavigate }) {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);
  const [rejectReason, setRejectReason] = useState("");
  const [showReject, setShowReject] = useState(false);
  const [poNote, setPoNote] = useState("");
  const [showPoRequest, setShowPoRequest] = useState(false);

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

  useEffect(load, [quoteId]); // 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 { quote, items, subtotal, taxAmount, total } = data;
  const canAct = !isReadOnly && quote.status !== "accepted" && quote.status !== "rejected";
  const hasPo = !!quote.po_number || !!quote.po_file_key;

  const doAccept = async () => {
    setBusy(true); setError("");
    try {
      const res = await fetch(`/api/admin/quotes/${quoteId}/accept`, { method: "POST", credentials: "same-origin" });
      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 doRequestPo = async () => {
    setBusy(true); setError("");
    try {
      const res = await fetch(`/api/admin/quotes/${quoteId}/request-po`, {
        method: "POST", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ note: poNote || undefined }),
      });
      const d = await res.json().catch(() => ({}));
      if (!res.ok) { setError(d.error || "Something went wrong."); setBusy(false); return; }
      setShowPoRequest(false); setPoNote("");
      load(); onSaved();
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
    } finally { setBusy(false); }
  };

  const doReject = async () => {
    if (!rejectReason.trim()) { setError("A reason is required to reject a quote."); return; }
    setBusy(true); setError("");
    try {
      const res = await fetch(`/api/admin/quotes/${quoteId}/reject`, {
        method: "POST", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ reason: rejectReason }),
      });
      const d = await res.json().catch(() => ({}));
      if (!res.ok) { setError(d.error || "Something went wrong."); setBusy(false); return; }
      setShowReject(false); setRejectReason("");
      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={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.24em", textTransform: "uppercase", color: "rgba(180,110,0,0.95)", fontWeight: 500, marginBottom: 12 }}>
        Line items ({items.length})
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 16 }}>
        {items.map((it) => (
          <div key={it.id} style={{
            display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap",
            padding: "8px 12px", background: "rgba(0,0,0,0.02)", border: "1px solid rgba(0,0,0,0.1)",
          }}>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.8)" }}>
              {it.product_name} × {it.quantity} @ {money(it.unit_price, quote.currency)}
            </div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.8)", fontWeight: 600 }}>
              {money(it.unit_price * it.quantity, quote.currency)}
            </div>
          </div>
        ))}
      </div>

      <div style={{ display: "grid", gap: 14, gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", marginBottom: 18 }}>
        <div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>Tax treatment</div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>
            {QUOTE_TAX_TREATMENT_LABELS[quote.tax_treatment] || quote.tax_treatment} ({quote.tax_rate}%)
          </div>
        </div>
        {quote.po_number && (
          <div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>PO number</div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{quote.po_number}</div>
          </div>
        )}
        {quote.po_file_key && (
          <div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>PO file</div>
            <a
              href={`/api/admin/quotes/${quoteId}/po/file`} target="_blank" rel="noreferrer"
              data-testid={`quote-po-file-link-${quoteId}`}
              style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(30,110,190,0.95)", textDecoration: "underline" }}
            >{quote.po_file_filename || "Download PDF"} →</a>
          </div>
        )}
        {quote.order_id && (
          <div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>Order</div>
            <button
              type="button" onClick={() => onNavigate("admin-orders")}
              style={{ background: "none", border: "none", padding: 0, cursor: "pointer", fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(30,110,190,0.95)", textDecoration: "underline" }}
            >Order #{quote.order_id} →</button>
          </div>
        )}
      </div>
      {quote.notes && (
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>Notes</div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", whiteSpace: "pre-wrap" }}>{quote.notes}</div>
        </div>
      )}
      {quote.status === "po_requested" && quote.po_requested_note && (
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(180,110,0,0.95)", marginBottom: 4 }}>PO request note</div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", whiteSpace: "pre-wrap" }}>{quote.po_requested_note}</div>
        </div>
      )}
      {quote.status === "rejected" && quote.rejected_reason && (
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(190,40,40,0.9)", marginBottom: 4 }}>Rejection reason</div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", whiteSpace: "pre-wrap" }}>{quote.rejected_reason}</div>
        </div>
      )}

      <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", marginBottom: 20 }}>
        Subtotal {money(subtotal, quote.currency)}
        {taxAmount > 0 && <> + Tax {money(taxAmount, quote.currency)}</>}
        {" "}→ Total <strong>{money(total, quote.currency)}</strong>
      </div>

      {canAct && (
        <div style={{ display: "flex", flexWrap: "wrap", gap: 10, borderTop: "1px solid rgba(0,0,0,0.1)", paddingTop: 18 }}>
          <ActionButton
            testId={`quote-accept-${quoteId}`}
            disabled={busy || !hasPo}
            onClick={doAccept}
          >
            {hasPo ? "Accept" : "Accept (needs PO)"}
          </ActionButton>
          <ActionButton
            testId={`quote-request-po-${quoteId}`}
            disabled={busy || quote.status === "po_requested"}
            onClick={() => setShowPoRequest((v) => !v)}
          >Request PO</ActionButton>
          <ActionButton
            testId={`quote-reject-${quoteId}`}
            danger
            disabled={busy}
            onClick={() => setShowReject((v) => !v)}
          >Reject</ActionButton>
        </div>
      )}
      {!hasPo && canAct && (
        <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.45)", marginTop: 8 }}>
          This quote needs a PO number or PO file from the reseller before it can be accepted.
        </div>
      )}

      {showPoRequest && canAct && (
        <div style={{ marginTop: 16, padding: "16px", background: "rgba(180,110,0,0.05)", border: "1px solid rgba(180,110,0,0.3)" }}>
          <MiniField label="Note to reseller (optional)">
            <textarea
              value={poNote} onChange={(e) => setPoNote(e.target.value)} rows={2}
              data-testid={`quote-po-note-${quoteId}`}
              style={{ ...adminInputStyle, resize: "vertical" }}
            />
          </MiniField>
          <div style={{ display: "flex", gap: 10 }}>
            <ActionButton testId={`quote-po-request-confirm-${quoteId}`} disabled={busy} onClick={doRequestPo}>Send request</ActionButton>
            <button type="button" onClick={() => setShowPoRequest(false)} style={{ background: "none", border: "none", cursor: "pointer", fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.5)" }}>Cancel</button>
          </div>
        </div>
      )}

      {showReject && canAct && (
        <div style={{ marginTop: 16, padding: "16px", background: "rgba(190,40,40,0.05)", border: "1px solid rgba(190,40,40,0.3)" }}>
          <MiniField label="Reason (required, shown to reseller)">
            <textarea
              value={rejectReason} onChange={(e) => setRejectReason(e.target.value)} rows={2}
              data-testid={`quote-reject-reason-${quoteId}`}
              style={{ ...adminInputStyle, resize: "vertical" }}
            />
          </MiniField>
          <div style={{ display: "flex", gap: 10 }}>
            <ActionButton testId={`quote-reject-confirm-${quoteId}`} danger disabled={busy} onClick={doReject}>Confirm reject</ActionButton>
            <button type="button" onClick={() => setShowReject(false)} style={{ background: "none", border: "none", cursor: "pointer", fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.5)" }}>Cancel</button>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { AdminQuotesPage });
