// /admin.html → WEBSITE tab. Per-product operational state editor backed by
// /api/admin/product-states. Writes propagate to every visitor immediately
// because the catalog/spotlight/modal/status page all read from the same
// /api/site/product-states feed via window.ExecStates.

(function () {
  const { useState, useEffect, useMemo, useCallback } = React;

  const STATE_OPTIONS = [
    { id: 'online',   label: 'ONLINE' },
    { id: 'updating', label: 'UPDATING' },
    { id: 'offline',  label: 'OFFLINE' },
  ];

  function AdminSiteApp() {
    // Re-render whenever ExecStates emits.
    window.ExecStates && window.ExecStates.useStates();
    window.ExecCatalog && window.ExecCatalog.useCatalog();
    window.ExecCategories && window.ExecCategories.useCategories();
    const products = window.ExecCatalog ? window.ExecCatalog.list() : [];
    const counts = window.ExecStates
      ? window.ExecStates.counts(products)
      : { online: 0, offline: 0, updating: 0, total: products.length };

    const [category, setCategory] = useState('all');

    const categories = useMemo(() => {
      const counts = {};
      for (const p of products) counts[p.category] = (counts[p.category] || 0) + 1;
      const live = window.ExecCategories ? window.ExecCategories.list() : [];
      return [
        { id: 'all', label: 'ALL', count: products.length },
        ...live.map((c) => ({ ...c, count: counts[c.id] || 0 })),
      ];
    }, [products]);

    const filtered = category === 'all' ? products : products.filter((p) => p.category === category);

    return (
      <>
        <window.HeroStrip user={null} isAdmin={true}>
          <window.StatColumn label="TOTAL"    value={String(counts.total)}/>
          <window.StatColumn label="ONLINE"   value={String(counts.online)}/>
          <window.StatColumn label="UPDATING" value={String(counts.updating)} accent={counts.updating > 0}/>
          <window.StatColumn label="OFFLINE"  value={String(counts.offline)}  accent={counts.offline  > 0}/>
        </window.HeroStrip>

        <div className="ap-sec-head">
          <div className="ap-sec-tag">// WEBSITE</div>
          <h2 className="ap-sec-title">PRODUCT STATES <span className="ap-sec-count">/ {filtered.length}</span></h2>
        </div>

        <div className="adm-toolbar">
          <window.CornerCuts size={8}/>
          <div className="adm-filter">
            <span className="adm-filter-label">CATEGORY</span>
            <select className="adm-select" value={category} onChange={(e) => setCategory(e.target.value)}>
              {categories.map((c) => (
                <option key={c.id} value={c.id}>{c.label} · {c.count}</option>
              ))}
            </select>
          </div>
          <div className="adm-toolbar-hint">
            Changes save instantly. The catalog, status page, and every counter on
            the site reflect updates within a second.
          </div>
        </div>

        <div className="adm-states">
          {filtered.map((p) => <StateRow key={p.id} product={p}/>)}
        </div>
      </>
    );
  }

  function StateRow({ product }) {
    const current = window.ExecStates
      ? window.ExecStates.get(product.id)
      : { state: 'updating', note: '' };

    const [note, setNote] = useState(current.note || '');
    const [saving, setSaving] = useState(null);    // null | 'state' | 'note'
    const [error, setError] = useState(null);
    const [lastSaved, setLastSaved] = useState(null);

    // Sync local note when remote changes from outside (e.g. another tab).
    useEffect(() => { setNote(current.note || ''); }, [current.note]);

    const save = useCallback(async (nextState, nextNote, kind) => {
      setSaving(kind); setError(null);
      try {
        await window.ExecStates.setState(product.id, nextState, nextNote);
        setLastSaved(Date.now());
      } catch (e) {
        setError(String(e && e.message || e));
      } finally {
        setSaving(null);
      }
    }, [product.id]);

    const onPickState = (e) => save(e.target.value, note, 'state');
    const onBlurNote = () => {
      if ((note || '') === (current.note || '')) return;
      save(current.state, note, 'note');
    };

    return (
      <div className={window.cls('adm-state-row', 'adm-state-row--' + current.state)}>
        <window.CornerCuts size={6}/>
        <div className="adm-state-tag">{product.tag}</div>
        <div className="adm-state-name">
          <span className="adm-state-cat">{(product.category || '').toUpperCase()}</span>
          <span className="adm-state-prod">{product.name}</span>
        </div>
        <div className="adm-state-pick">
          <span className={`st-pill ${current.state}`}>
            <span className="st-pill-dot"></span>
            <span>{current.state.toUpperCase()}</span>
          </span>
          <select
            className="adm-select"
            value={current.state}
            onChange={onPickState}
            disabled={saving === 'state'}
          >
            {STATE_OPTIONS.map((o) => <option key={o.id} value={o.id}>{o.label}</option>)}
          </select>
        </div>
        <div className="adm-state-note">
          <input
            type="text"
            className="adm-state-note-input"
            placeholder="optional note (e.g. v0.9.7 patch deploying)"
            value={note}
            onChange={(e) => setNote(e.target.value)}
            onBlur={onBlurNote}
            onKeyDown={(e) => { if (e.key === 'Enter') e.currentTarget.blur(); }}
            maxLength={240}
            disabled={saving === 'note'}
          />
        </div>
        <div className="adm-state-meta">
          {saving && <span className="adm-state-saving">saving…</span>}
          {!saving && error && <span className="adm-state-err" title={error}>save failed</span>}
          {!saving && !error && lastSaved && <span className="adm-state-ok">saved</span>}
        </div>
      </div>
    );
  }

  window.AdminSiteApp = AdminSiteApp;
})();
