// Solo staff admin area — User Manuals: a reseller-facing PDF document
// library, distinct from Spec Sheets (admin-spec-sheets-page.jsx, which
// edits products.spec_sheet_*). Customer's explicit brief: "not for the
// website but for resellers to view... PDF uploads like the spec
// sheets... downloadable by the reseller... name field manual entered by
// the admin for now, 10 slots should be enough for now."
//
// Backed by a FIXED set of 10 pre-seeded rows (migrations/0052) rather
// than an open-ended catalogue — each slot has a free-text `name` field
// staff type in themselves (no product/lookup relationship) plus an
// optional uploaded PDF (stored in R2 — see the /user-manuals* routes in
// admin-user-manuals.ts). Reached via the sidebar nav in AdminShell (see
// admin-shell.jsx). Reuses MiniField/ActionButton/SectionLabel/EmptyNote/
// ModalError/adminInputStyle from admin-assets-page.jsx (loaded earlier —
// see index.html), same pattern as admin-spec-sheets-page.jsx.

const formatManualBytes = (bytes) => {
  if (!bytes) return "";
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
};

const formatManualDate = (iso) => {
  if (!iso) return "";
  try {
    return new Date(iso).toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" });
  } catch {
    return "";
  }
};

function AdminUserManualsPage({ onNavigate }) {
  const [state, setState] = useState({ status: "loading", admin: null, manuals: [] });
  const [error, setError] = useState("");

  const load = () => {
    Promise.all([
      fetch("/api/admin/me", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
      fetch("/api/admin/user-manuals", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
    ])
      .then(([me, manuals]) => {
        setState({ status: "ready", admin: me.admin, manuals: manuals.manuals || [] });
      })
      .catch(() => onNavigate("admin-login"));
  };

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

  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-user-manuals" onNavigate={onNavigate}
      subtitle="Staff only" title="User manuals.">
      <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.6)", marginBottom: 24, maxWidth: 760, lineHeight: 1.6 }}>
        Upload PDF user manuals for resellers to view and download from their portal. Name each slot yourself — there's no link to a specific product, so use whatever label makes sense (e.g. "Solo PCT — Installation Guide", "Firmware v2 release notes"). A slot only shows up in the reseller portal once it has BOTH a name and an uploaded PDF.
      </div>
      {error && <ModalError>{error}</ModalError>}

      <SectionLabel>Manual slots ({state.manuals.length})</SectionLabel>
      <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        {state.manuals.map((m) => (
          <UserManualRow key={m.id} manual={m} isReadOnly={isReadOnly} onError={setError} onSaved={load} />
        ))}
      </div>
    </AdminShell>
  );
}

function UserManualRow({ manual, isReadOnly, onError, onSaved }) {
  const [name, setName] = useState(manual.name || "");
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [removing, setRemoving] = useState(false);
  const fileInputRef = useRef(null);

  useEffect(() => { setName(manual.name || ""); }, [manual.name]);

  const dirty = name.trim() !== (manual.name || "");
  const hasFile = Boolean(manual.file_key);
  const hasName = Boolean((manual.name || "").trim());
  const openHref = hasFile ? `/api/admin/user-manuals/${manual.id}/file` : null;
  const visibleToResellers = hasFile && hasName;

  const saveName = async () => {
    setSaving(true);
    onError("");
    try {
      const res = await fetch(`/api/admin/user-manuals/${manual.id}/name`, {
        method: "PATCH", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: name.trim() }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { onError(data.error || "Something went wrong."); return; }
      setSaved(true);
      onSaved();
      setTimeout(() => setSaved(false), 1800);
    } catch {
      onError("Couldn't reach the server. Check your connection and try again.");
    } finally {
      setSaving(false);
    }
  };

  const pickFile = () => fileInputRef.current && fileInputRef.current.click();

  const uploadFile = async (file) => {
    if (!file) return;
    onError("");
    setUploading(true);
    try {
      const formData = new FormData();
      formData.append("file", file);
      const res = await fetch(`/api/admin/user-manuals/${manual.id}/file`, {
        method: "POST", credentials: "same-origin", body: formData,
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { onError(data.error || "Couldn't upload that PDF."); return; }
      onSaved();
    } catch {
      onError("Couldn't reach the server. Check your connection and try again.");
    } finally {
      setUploading(false);
    }
  };

  const onFileChange = (e) => {
    const file = e.target.files && e.target.files[0];
    e.target.value = ""; // allow re-selecting the same filename later
    if (file) uploadFile(file);
  };

  const removeFile = async () => {
    onError("");
    setRemoving(true);
    try {
      const res = await fetch(`/api/admin/user-manuals/${manual.id}/file`, {
        method: "DELETE", credentials: "same-origin",
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { onError(data.error || "Couldn't remove that PDF."); return; }
      onSaved();
    } catch {
      onError("Couldn't reach the server. Check your connection and try again.");
    } finally {
      setRemoving(false);
    }
  };

  return (
    <div data-testid={`user-manual-row-${manual.id}`} style={{
      background: "rgba(0,0,0,0.02)", border: "1px solid rgba(0,0,0,0.14)", padding: "18px 20px",
      display: "flex", alignItems: "flex-end", gap: 16, flexWrap: "wrap",
    }}>
      <div style={{ minWidth: 64, flex: "0 0 64px" }}>
        <div style={{
          fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 15,
          textTransform: "uppercase", color: "#000",
        }}>Slot {manual.slot_number}</div>
        <div style={{
          fontFamily: "var(--font-body)", fontSize: 10.5, letterSpacing: "0.06em",
          textTransform: "uppercase", marginTop: 4,
          color: visibleToResellers ? "rgba(20,140,60,0.95)" : "rgba(0,0,0,0.4)",
        }}>
          {visibleToResellers ? "Live" : "Hidden"}
        </div>
      </div>

      <div style={{ flex: "1 1 320px", minWidth: 240 }}>
        <MiniField label="Manual name">
          <input
            value={name}
            onChange={(e) => setName(e.target.value)}
            onKeyDown={(e) => { if (e.key === "Enter") saveName(); }}
            placeholder="e.g. Solo PCT — Installation Guide"
            data-testid={`user-manual-name-input-${manual.id}`}
            style={{ ...adminInputStyle, width: "100%" }}
          />
        </MiniField>
      </div>

      <div style={{ display: "flex", alignItems: "center", gap: 10, paddingBottom: 2 }}>
        {openHref && (
          <a
            href={openHref} target="_blank" rel="noopener noreferrer"
            data-testid={`user-manual-open-${manual.id}`}
            style={{
              fontFamily: "var(--font-body)", fontSize: 11.5, fontWeight: 500,
              letterSpacing: "0.08em", textTransform: "uppercase",
              color: "rgba(180,110,0,0.95)", textDecoration: "none",
              border: "1px solid rgba(180,110,0,0.4)", padding: "9px 14px",
              whiteSpace: "nowrap",
            }}
          >
            Open ↗
          </a>
        )}
        <ActionButton
          onClick={saveName}
          disabled={!dirty || saving}
          readOnly={isReadOnly}
          testId={`user-manual-save-${manual.id}`}
        >
          {saving ? "Saving…" : "Save name"}
        </ActionButton>
        {saved && !saving && (
          <span style={{ fontFamily: "var(--font-body)", fontSize: 10.5, color: "rgba(20,140,60,0.95)" }}>Saved ✓</span>
        )}
      </div>

      <div style={{
        flex: "1 1 100%", display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap",
        borderTop: "1px solid rgba(0,0,0,0.1)", paddingTop: 14, marginTop: 2,
      }}>
        <div style={{
          fontFamily: "var(--font-body)", fontSize: 10.5, letterSpacing: "0.08em",
          textTransform: "uppercase", color: "rgba(0,0,0,0.45)", whiteSpace: "nowrap",
        }}>
          PDF upload
        </div>

        {hasFile ? (
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12.5, color: "rgba(0,0,0,0.8)" }}>
            <i className="fas fa-file-pdf" style={{ color: "rgba(190,40,40,0.9)", marginRight: 6 }} />
            {manual.file_filename || "manual.pdf"}
            <span style={{ color: "rgba(0,0,0,0.45)", marginLeft: 8 }}>
              {[formatManualBytes(manual.file_size), formatManualDate(manual.uploaded_at)].filter(Boolean).join(" · ")}
            </span>
          </div>
        ) : (
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12.5, color: "rgba(0,0,0,0.45)" }}>
            No PDF uploaded yet.
          </div>
        )}

        <input
          ref={fileInputRef}
          type="file"
          accept="application/pdf"
          onChange={onFileChange}
          data-testid={`user-manual-file-input-${manual.id}`}
          style={{ display: "none" }}
        />
        <ActionButton
          onClick={pickFile}
          disabled={uploading || removing}
          readOnly={isReadOnly}
          testId={`user-manual-upload-${manual.id}`}
        >
          {uploading ? "Uploading…" : hasFile ? "Replace PDF" : "Upload PDF"}
        </ActionButton>
        {hasFile && (
          <ActionButton
            onClick={removeFile}
            disabled={uploading || removing}
            readOnly={isReadOnly}
            danger
            testId={`user-manual-remove-${manual.id}`}
          >
            {removing ? "Removing…" : "Remove PDF"}
          </ActionButton>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { AdminUserManualsPage });
