// Catalogue Feed section (BOO-136) — lives on the API Keys (developer
// settings) screen. Documents how to consume the pre-generated availability
// feed files in GCS instead of bulk-calling the live availability API:
// base URL, path patterns, discovery, freshness, and one live example URL
// from the partner's own catalogue. Deliberately not a file browser.

function CatalogueFeedSection() {
  const [data, setData] = React.useState(null); // null = loading
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    ppLoadCatalogueFeed()
      .then((d) => { if (!cancelled) setData(d || {}); })
      .catch((e) => { if (!cancelled) { setError(e?.message || 'Could not load feed details.'); setData({}); } });
    return () => { cancelled = true; };
  }, []);

  const windowDays = (data && data.windowDays) || 90;
  const refreshHours = (data && data.refreshHours) || 4;
  const baseUrl = data && data.baseUrl ? data.baseUrl.replace(/\/+$/, '') : null;

  return (
    <section className="pp-keys-section">
      <header className="pp-keys-section-head">
        <p className="pp-keys-section-sub">
          Bulk availability as static files — one download covers a product's whole {windowDays}-day
          window, every party size, instead of hundreds of live availability calls.
        </p>
      </header>

      {error && <div className="pp-banner-warn"><FeedAlertGlyph size={14}/><span>{error}</span></div>}

      {data === null ? (
        <div className="pp-key-card pp-key-card--loading"><span className="pp-muted" style={{ fontSize: 13 }}>Loading…</span></div>
      ) : (
        <React.Fragment>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', margin: '0 0 12px' }}>
            <span className="pp-prod-pill">{data.generatedAt ? ('Generated ' + ppFeedAgo(data.generatedAt)) : 'Awaiting first run'}</span>
            <span className="pp-prod-pill">{windowDays}-day window</span>
            <span className="pp-prod-pill">Refreshes every ~{refreshHours} h</span>
            <span className="pp-prod-pill">Gzipped JSON · no auth on files</span>
          </div>

          {baseUrl && (
            <div className="pp-key-card" style={{ display: 'block' }}>
              <FeedCopyField label="Base URL" value={baseUrl}/>
              <div className="pp-key-meta" style={{ marginTop: 8 }}>
                <span>One file per product:&nbsp;</span>
                <span className="pp-mono">{'{venueGroupId}/{venueId}/{productId}.json.gz'}</span>
              </div>
              {data.partnerId && (
                <div className="pp-key-meta">
                  <span>Your partner-customised file (only where operators tailor rules for you):&nbsp;</span>
                  <span className="pp-mono">{'{venueGroupId}/{venueId}/{productId}.' + data.partnerId + '.json.gz'}</span>
                </div>
              )}
            </div>
          )}

          <div className="pp-key-card" style={{ display: 'block' }}>
            <div className="pp-key-card-name" style={{ marginBottom: 6 }}>How to find and use your files</div>
            <ol className="pp-muted" style={{ fontSize: 13, lineHeight: 1.7, margin: 0, paddingLeft: 18 }}>
              <li><span className="pp-mono">GET /venues</span> on the Bookable API lists your venues; every product carries a <span className="pp-mono">compositeId</span> of the form <span className="pp-mono">{'{venueGroupId}|{rms}|{venueId}|{productId}'}</span>. Drop the <span className="pp-mono">rms</span> segment and join the rest with slashes to get the file path.</li>
              {data.listUrl && (
                <li>Enumerate all of a venue's files in one call: <span className="pp-mono">GET {data.listUrl}?prefix={'{venueGroupId}/{venueId}/'}</span> — works for a whole venue group too (<span className="pp-mono">prefix={'{venueGroupId}/'}</span>).</li>
              )}
              <li>Each file holds every bookable slot for the next {windowDays} days, all party sizes, as time ranges with live-deducted capacity (<span className="pp-mono">spots_open</span>). Filter your copy locally — there is no server-side filtering.</li>
              <li>Re-pull on your own schedule; files refresh every ~{refreshHours} hours. Send <span className="pp-mono">If-None-Match</span> with the ETag to skip unchanged files.</li>
              <li>Keep creating bookings through the API — the booking call re-validates the slot live, so feed staleness can't double-book.</li>
            </ol>
          </div>

          {data.example && (
            <div className="pp-key-card" style={{ display: 'block' }}>
              <div className="pp-key-card-name" style={{ marginBottom: 6 }}>
                Try it — {data.example.productName} at {data.example.venueName}
              </div>
              <FeedCopyField label={data.example.partnerUrl ? 'Global file' : 'Feed URL'} value={data.example.url}/>
              {data.example.partnerUrl && (
                <FeedCopyField label="Your customised file" value={data.example.partnerUrl}/>
              )}
              <pre className="pp-mono" style={{ fontSize: 12, background: 'var(--pp-cream, #faf7f2)', border: '1px solid var(--pp-line, #e8e2d8)', borderRadius: 8, padding: '10px 12px', overflowX: 'auto', margin: '10px 0 0' }}>
{'curl -s "' + (data.example.partnerUrl || data.example.url) + '" | gunzip > availability.json'}
              </pre>
              <div className="pp-key-meta" style={{ marginTop: 8 }}>
                {data.example.updatedAt && <span>Updated {ppFeedAgo(data.example.updatedAt)}</span>}
                {data.example.sizeBytes != null && <span>· {ppFeedSize(data.example.sizeBytes)} compressed</span>}
              </div>
            </div>
          )}
        </React.Fragment>
      )}
    </section>
  );
}

function FeedCopyField({ label, value }) {
  const [copied, setCopied] = React.useState(false);
  const copy = async () => {
    try {
      await navigator.clipboard.writeText(value);
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch (e) { /* clipboard blocked — value is still selectable */ }
  };
  return (
    <div className="pp-copy-field">
      <span className="pp-copy-field-label">{label}</span>
      <div className="pp-copy-field-row">
        <code className="pp-copy-field-value pp-mono" style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{value}</code>
        <button type="button" className="pp-btn pp-btn--ghost pp-btn--xs" onClick={copy}>
          {copied ? <React.Fragment><IconCheck size={12}/> Copied</React.Fragment> : 'Copy'}
        </button>
      </div>
    </div>
  );
}

function ppFeedAgo(iso) {
  const t = new Date(iso).getTime();
  if (isNaN(t)) return iso;
  const mins = Math.max(0, Math.round((Date.now() - t) / 60000));
  if (mins < 60) return mins + ' min ago';
  const hours = Math.round(mins / 60);
  if (hours < 48) return hours + ' h ago';
  return Math.round(hours / 24) + ' days ago';
}

function ppFeedSize(bytes) {
  if (bytes >= 1048576) return (bytes / 1048576).toFixed(1) + ' MB';
  if (bytes >= 1024) return Math.round(bytes / 1024) + ' KB';
  return bytes + ' B';
}

// ── inline glyphs (not in icons.jsx) ────────────────────────────────────────
function FeedAlertGlyph({ size = 14 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 9v4M12 17v.01"/><path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/>
    </svg>
  );
}

Object.assign(window, { CatalogueFeedSection });
