/* My Stash: the signed-in, read-only view of the user's synced inventory.
   Data comes from GET /api/items (paged, server-side search + type filter).
   The desktop app is the source of truth; nothing here edits anything. */

const STASH_TYPES = [
  "Adhesives", "Card Bases", "Cardstock", "Color Inspiration", "Combo Club",
  "Dies", "Embellishments", "Embossing Folders", "Envelopes", "Foils",
  "Inks", "Kits", "Labeling", "Miscellaneous", "OLO Markers", "Stacklets",
  "Stamps", "Stencils", "Storage", "Tools", "Watercolor",
];

const STASH_PER_PAGE = 24;

function StashPage({ go, user }) {
  // user: undefined = auth check in flight, null = signed out, object = signed in
  const [search, setSearch] = React.useState("");
  const [type, setType] = React.useState("");
  const [items, setItems] = React.useState([]);
  const [page, setPage] = React.useState(1);
  const [total, setTotal] = React.useState(null);
  const [totalPages, setTotalPages] = React.useState(0);
  const [loading, setLoading] = React.useState(true);
  const [loadingMore, setLoadingMore] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [detail, setDetail] = React.useState(null);
  const debouncedSearch = useDebounced(search, 350);

  // Signed out -> straight to Google, then back here.
  React.useEffect(() => {
    if (user === null) {
      window.location.href = "/.auth/login/google?post_login_redirect_uri=/%23stash";
    }
  }, [user]);

  const fetchPage = React.useCallback(async (pageNum, append) => {
    const params = new URLSearchParams({ page: pageNum, perPage: STASH_PER_PAGE });
    if (debouncedSearch) params.set("search", debouncedSearch);
    if (type) params.set("type", type);

    const resp = await fetch(`/api/items?${params}`);
    if (resp.status === 401) {
      window.location.href = "/.auth/login/google?post_login_redirect_uri=/%23stash";
      return;
    }
    if (!resp.ok) throw new Error(`Server returned ${resp.status}`);
    const data = await resp.json();
    setItems((prev) => (append ? [...prev, ...data.items] : data.items));
    setTotal(data.total);
    setTotalPages(data.totalPages);
    setPage(data.page);
  }, [debouncedSearch, type]);

  // First page (re)load whenever the filters change.
  React.useEffect(() => {
    if (!user) return;
    let cancelled = false;
    setLoading(true);
    setError(null);
    fetchPage(1, false)
      .catch((e) => { if (!cancelled) setError(e.message); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [user, fetchPage]);

  const loadMore = async () => {
    setLoadingMore(true);
    try { await fetchPage(page + 1, true); }
    catch (e) { setError(e.message); }
    finally { setLoadingMore(false); }
  };

  if (!user) {
    return (
      <div className="page" data-screen-label="08 My Stash">
        <StashCentered>
          <div className="stash-spinner" />
          <p className="kicker" style={{ marginTop: 16 }}>
            {user === null ? "Sending you to sign in..." : "Checking who you are..."}
          </p>
        </StashCentered>
      </div>
    );
  }

  const hasFilters = debouncedSearch || type;
  const showEmpty = !loading && !error && total === 0 && !hasFilters;
  const showNoMatches = !loading && !error && total === 0 && hasFilters;

  return (
    <div className="page" data-screen-label="08 My Stash">
      <section className="section" style={{ paddingTop: 28 }}>
        <div className="container" style={{ maxWidth: 1180 }}>

          <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", flexWrap: "wrap", gap: 8, marginBottom: 18 }}>
            <h2 style={{ margin: 0 }}>My Stash</h2>
            {total !== null && total > 0 && (
              <span className="kicker">
                {total} item{total === 1 ? "" : "s"}{hasFilters ? " matching" : ""}
              </span>
            )}
          </div>

          <div className="stash-toolbar">
            <input
              type="search"
              className="stash-search"
              placeholder="Search name, number, theme, sentiment..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
            />
            <select className="stash-type" value={type} onChange={(e) => setType(e.target.value)}>
              <option value="">All types</option>
              {STASH_TYPES.map((t) => <option key={t} value={t}>{t}</option>)}
            </select>
          </div>

          {error && (
            <StashCentered>
              <p className="lead" style={{ marginBottom: 8 }}>Something went wrong loading your stash.</p>
              <p className="kicker" style={{ marginBottom: 20 }}>{error}</p>
              <button className="btn" onClick={() => { setError(null); setLoading(true); fetchPage(1, false).catch((e) => setError(e.message)).finally(() => setLoading(false)); }}>
                Try again
              </button>
              <p className="kicker" style={{ marginTop: 18 }}>
                If this keeps happening, email Silosoftwarecreations@gmail.com
              </p>
            </StashCentered>
          )}

          {loading && !error && (
            <div className="stash-grid">
              {Array.from({ length: 8 }).map((_, i) => <div key={i} className="stash-skeleton" />)}
            </div>
          )}

          {showEmpty && <StashEmptyState go={go} />}

          {showNoMatches && (
            <StashCentered>
              <p className="lead" style={{ marginBottom: 8 }}>
                No matches{debouncedSearch ? <> for &ldquo;{debouncedSearch}&rdquo;</> : ""}.
              </p>
              <button className="btn" onClick={() => { setSearch(""); setType(""); }}>Clear search</button>
            </StashCentered>
          )}

          {!loading && !error && items.length > 0 && (
            <>
              <div className="stash-grid">
                {items.map((item) => (
                  <StashCard key={item.id} item={item} onOpen={() => setDetail(item)} />
                ))}
              </div>
              {page < totalPages && (
                <div style={{ textAlign: "center", marginTop: 28 }}>
                  <button className="btn" onClick={loadMore} disabled={loadingMore}>
                    {loadingMore ? "Loading..." : `Load more (${items.length} of ${total})`}
                  </button>
                </div>
              )}
            </>
          )}
        </div>
      </section>

      {detail && <StashDetail item={detail} onClose={() => setDetail(null)}
        onSearchSentiment={(s) => { setDetail(null); setType(""); setSearch(s); }} />}
    </div>
  );
}

function StashCard({ item, onOpen }) {
  const img = item.thumbUrl || item.imageUrl;
  const lowStock = item.currentStock !== null && item.currentStock !== undefined && item.currentStock <= 1;
  return (
    <button className="stash-card" onClick={onOpen}>
      <div className="stash-card-photo">
        {img
          ? <img src={img} alt={item.name} loading="lazy" />
          : <div className="stash-card-noimg">No photo</div>}
        {lowStock && (
          <span className="stash-stock-dot" title={`${item.currentStock} in stock`}>
            {item.currentStock}
          </span>
        )}
        {item.isDiscontinued && <span className="stash-pill-disc">Discontinued</span>}
      </div>
      <div className="stash-card-name">{item.name}</div>
      <div className="kicker" style={{ marginTop: 2 }}>{item.type}</div>
    </button>
  );
}

/* Detail overlay. Uses the fields already in the list response; the richer
   /api/items/:id endpoint (purchases, related items, sentiment snips) is a
   later phase. */
function StashDetail({ item, onClose, onSearchSentiment }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [onClose]);

  const stock = item.currentStock;
  const stockText =
    stock === null || stock === undefined ? null :
    stock === 0 ? ["Out of stock", "var(--accent-deep)"] :
    stock <= 1 ? [`Low (${stock} left)`, "var(--accent)"] :
    [`${stock} in stock`, "var(--ink-2)"];

  const meta = [
    ["Item number", item.itemNumber],
    ["Theme", item.theme],
    ["Subtype", item.subtype],
    ["Price", item.price !== null && item.price !== undefined ? `$${Number(item.price).toFixed(2)}` : null],
    ["Date purchased", item.datePurchased],
    ["Purchased from", item.purchasedFrom],
    ["Location", item.location],
    ["Notes", item.notes],
  ].filter(([, v]) => v !== null && v !== undefined && v !== "");

  return (
    <div className="stash-overlay" onClick={onClose}>
      <div className="stash-detail card bordered" onClick={(e) => e.stopPropagation()}>
        <button className="stash-close" onClick={onClose} aria-label="Close">×</button>
        {item.imageUrl && (
          <div className="stash-detail-photo">
            <img src={item.imageUrl} alt={item.name} />
          </div>
        )}
        <div style={{ padding: "18px 22px 24px" }}>
          <h3 style={{ margin: "0 0 10px", fontFamily: "var(--display-font)" }}>{item.name}</h3>
          <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
            <span className="stash-badge">{item.type}</span>
            {item.isDiscontinued && <span className="stash-badge" style={{ background: "var(--paper-3)" }}>Discontinued</span>}
            {stockText && <span className="stash-badge" style={{ color: stockText[1] }}>{stockText[0]}</span>}
          </div>

          {Array.isArray(item.sentiments) && item.sentiments.length > 0 && (
            <div style={{ marginBottom: 14 }}>
              <div className="kicker" style={{ marginBottom: 6 }}>Sentiments</div>
              <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                {item.sentiments.map((s, i) => (
                  <button key={i} className="stash-sentiment" onClick={() => onSearchSentiment(s)}>{s}</button>
                ))}
              </div>
            </div>
          )}

          <div className="stash-meta">
            {meta.map(([k, v]) => (
              <React.Fragment key={k}>
                <div className="kicker">{k}</div>
                <div style={{ fontSize: "0.95rem" }}>{v}</div>
              </React.Fragment>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function StashEmptyState({ go }) {
  return (
    <StashCentered>
      <div style={{ width: 72, height: 72, borderRadius: "50%", background: "var(--accent-soft)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 30, marginBottom: 18 }}>📦</div>
      <h3 style={{ margin: "0 0 8px" }}>Nothing here yet.</h3>
      <p className="lead" style={{ maxWidth: 460, marginBottom: 22 }}>
        Open My Crafty Stash on your PC, set up Cloud Sync in Settings, and your
        stash will appear here a minute or two later.
      </p>
      <ol style={{ textAlign: "left", margin: "0 0 24px", paddingLeft: 22, color: "var(--ink-2)", lineHeight: 2 }}>
        <li>Open the desktop app</li>
        <li>Settings → Cloud Sync</li>
        <li>Paste an API key from the Keys page, hit Sync now</li>
      </ol>
      <button className="btn" onClick={() => go("download")}>
        Don't have the desktop app yet?
      </button>
    </StashCentered>
  );
}

function StashCentered({ children }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center", padding: "64px 20px" }}>
      {children}
    </div>
  );
}

function useDebounced(value, delayMs) {
  const [debounced, setDebounced] = React.useState(value);
  React.useEffect(() => {
    const t = setTimeout(() => setDebounced(value), delayMs);
    return () => clearTimeout(t);
  }, [value, delayMs]);
  return debounced;
}

Object.assign(window, { StashPage });
