// Solo staff admin area — Orders: a sales order that goes into the build
// queue and is tracked ordered -> in_build -> ready_to_ship -> shipped (or
// cancelled). Deliberately does NOT touch serialized asset_units — see
// migrations/0004_crm.sql. 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).
//
// READ-ONLY ON PURPOSE (accounting fields): order records will be pulled
// from Xero/QuickBooks rather than typed in here, so create/edit/line-item
// controls have been removed from this page (and the backing endpoints in
// routes/admin-orders.ts). Staff can still VIEW every order and progress
// its physical build-stage status, which stays local to Solo Secure and
// has no Xero/QuickBooks equivalent.

const ORDER_STATUS_LABELS_UI = { ordered: "Ordered", in_build: "In Build", ready_to_ship: "Ready to Ship", shipped: "Shipped", cancelled: "Cancelled" };
const ORDER_STATUS_COLORS = {
  ordered: "rgba(0,0,0,0.55)",
  in_build: "rgba(180,110,0,0.95)",
  ready_to_ship: "rgba(30,110,190,0.95)",
  shipped: "rgba(20,140,60,0.95)",
  cancelled: "rgba(190,40,40,0.9)",
};
const ORDER_STATUS_FLOW = ["ordered", "in_build", "ready_to_ship", "shipped", "cancelled"];

// Xero sync status badge — order.xero_sync_status is one of NULL (never
// touched, e.g. predates the feature), 'unlinked' (Xero connected but this
// company has no bound contact yet), 'synced', or 'failed'. NULL and
// 'unlinked' are both shown as "Not linked" so staff only ever see 3 states.
const XERO_SYNC_LABELS = { synced: "Synced ✓", unlinked: "Not linked", failed: "Failed" };
const XERO_SYNC_COLORS = {
  synced: "rgba(20,140,60,0.95)",
  unlinked: "rgba(0,0,0,0.4)",
  failed: "rgba(190,40,40,0.9)",
};
function xeroSyncKey(status) {
  return status === "synced" || status === "failed" ? status : "unlinked";
}
function XeroSyncBadge({ status, error, compact }) {
  const key = xeroSyncKey(status);
  return (
    <span
      title={key === "failed" ? (error || "Xero sync failed.") : undefined}
      data-testid="xero-sync-badge"
      style={{
        display: "inline-block",
        fontFamily: "var(--font-body)",
        fontSize: compact ? 10 : 11,
        fontWeight: 500,
        letterSpacing: "0.06em",
        textTransform: "uppercase",
        color: XERO_SYNC_COLORS[key],
        border: `1px solid ${XERO_SYNC_COLORS[key]}`,
        borderRadius: 3,
        padding: compact ? "1px 6px" : "3px 9px",
        cursor: key === "failed" ? "help" : "default",
      }}
    >
      {XERO_SYNC_LABELS[key]}
    </span>
  );
}

function AdminOrdersPage({ onNavigate }) {
  const [state, setState] = useState({ status: "loading", admin: null, orders: [], 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/orders?${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, orders, companies]) => {
        setState({
          status: "ready", admin: me.admin,
          orders: orders.orders || [], 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-orders" onNavigate={onNavigate}
      subtitle="Staff only — read-only, pulled from Xero/QuickBooks" title="Orders.">
      <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>
            {ORDER_STATUS_FLOW.map((s) => <option key={s} value={s}>{ORDER_STATUS_LABELS_UI[s]}</option>)}
          </select>
        </MiniField>
      </div>

      <SectionLabel>Orders ({state.orders.length})</SectionLabel>
      {state.orders.length === 0 ? (
        <EmptyNote>No orders raised yet.</EmptyNote>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {state.orders.map((o) => (
            <OrderRow
              key={o.id} order={o}
              open={openId === o.id} isReadOnly={isReadOnly}
              onToggle={() => setOpenId(openId === o.id ? null : o.id)}
              onSaved={load}
            />
          ))}
        </div>
      )}
    </AdminShell>
  );
}

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

function OrderRow({ order, open, isReadOnly, onToggle, onSaved }) {
  return (
    <div data-testid={`order-row-${order.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={`order-toggle-${order.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" }}>
            Order #{order.id} <span style={{ color: "rgba(0,0,0,0.55)", fontSize: 12, fontWeight: 400 }}>· {order.company_name}</span>
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.55)", marginTop: 4 }}>
            <span style={{ color: ORDER_STATUS_COLORS[order.status] || "rgba(0,0,0,0.55)", textTransform: "uppercase", letterSpacing: "0.08em", fontSize: 11 }}>
              {ORDER_STATUS_LABELS_UI[order.status] || order.status}
            </span>
            {" · "}{order.item_count} item{order.item_count === 1 ? "" : "s"} · {money(order.total, order.currency)}
            {order.purchase_order_number && <> · PO {order.purchase_order_number}</>}
          </div>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <XeroSyncBadge status={order.xero_sync_status} error={order.xero_sync_error} compact />
          <span style={{ fontFamily: "var(--font-body)", fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.55)" }}>
            {open ? "Close ↑" : "Amend →"}
          </span>
        </div>
      </button>
      {open && <OrderDetail orderId={order.id} isReadOnly={isReadOnly} onSaved={onSaved} />}
    </div>
  );
}

function OrderDetail({ orderId, isReadOnly, onSaved }) {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);

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

  useEffect(load, [orderId]); // 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 { order, items, history } = data;

  // Build-stage status is the ONLY thing staff can still change here — it's
  // Solo's own internal fulfilment tracking and has no Xero/QuickBooks
  // equivalent. Every accounting field (line items, discount, notes, PO
  // link) is read-only, pulled from Xero/QuickBooks instead.
  const changeStatus = async (next) => {
    setBusy(true);
    setError("");
    try {
      const res = await fetch(`/api/admin/orders/${orderId}/status`, {
        method: "POST", 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 subtotal = items.reduce((sum, it) => sum + it.unit_price * it.quantity * (1 - (it.discount_percent || 0) / 100), 0);

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

      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 14 }}>
        <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.24em", textTransform: "uppercase", color: "rgba(0,0,0,0.4)", fontWeight: 500 }}>
          Xero
        </div>
        <XeroSyncBadge status={order.xero_sync_status} error={order.xero_sync_error} />
      </div>

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

      <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}) <span style={{ color: "rgba(0,0,0,0.35)", textTransform: "none", letterSpacing: 0, fontSize: 11 }}>— read-only, from Xero/QuickBooks</span>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 16 }}>
        {items.map((it) => (
          <div key={it.id} style={{
            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, order.currency)}
              {it.discount_percent ? ` (-${it.discount_percent}%)` : ""}
            </div>
          </div>
        ))}
      </div>

      {(order.discount_percent > 0 || order.notes || order.purchase_order_number) && (
        <div style={{ display: "grid", gap: 14, gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", marginBottom: 16 }}>
          {order.discount_percent > 0 && (
            <div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: "rgba(0,0,0,0.4)", marginBottom: 4 }}>Order discount</div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{order.discount_percent}%</div>
            </div>
          )}
          {order.purchase_order_number && (
            <div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: "rgba(0,0,0,0.4)", marginBottom: 4 }}>PO reference</div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{order.purchase_order_number}</div>
            </div>
          )}
          {order.notes && (
            <div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: "rgba(0,0,0,0.4)", marginBottom: 4 }}>Notes</div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{order.notes}</div>
            </div>
          )}
        </div>
      )}

      <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", marginBottom: 20 }}>
        Subtotal {money(subtotal, order.currency)} → Total <strong>{money(subtotal * (1 - (order.discount_percent || 0) / 100), order.currency)}</strong>
      </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 }}>
        Status history
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
        {history.map((h) => (
          <div key={h.id} style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.55)" }}>
            {h.changed_at} — <span style={{ color: "rgba(0,0,0,0.8)" }}>{ORDER_STATUS_LABELS_UI[h.status] || h.status}</span>
            {h.changed_by_name && <> by {h.changed_by_name}</>}
            {h.notes && <> — {h.notes}</>}
          </div>
        ))}
      </div>
    </div>
  );
}

Object.assign(window, { AdminOrdersPage });
