// Static Ads — image-ad generation surface. Standalone product: it drives the
// existing static_ads backend (POC orchestrator -> RabbitMQ lane -> S3) and only
// renders the run form, live progress, and the variants gallery/history. No
// pipeline logic lives here. Mirrors AutoRemodelPanel.jsx conventions.
const { useState: useSAState, useEffect: useSAEffect } = React;

const STATIC_ADS_VARIANTS_MAX = 10;
const STATIC_ADS_VARIANTS_DEFAULT = 4;
// Backend only emits coarse status + a 0.0–1.0 fraction (0.05 the whole time a
// run is "running"), so the named sub-steps from the ticket are not authoritative.
const SA_STRICTNESS_OPTIONS = ['strict', 'medium', 'loose'];

function _saStatusText(status) {
  switch (status) {
    case 'queued': return 'Queued…';
    case 'running': return 'Generating variants…';
    case 'done': return 'Complete';
    case 'failed': return 'Failed';
    case 'cancelled': return 'Stopped';
    default: return status || 'Idle';
  }
}

function _saStatusClass(status) {
  if (status === 'done') return 'ok';
  if (status === 'failed') return 'err';
  if (status === 'cancelled') return 'warn';
  return 'run';
}

function _saMoney(n) {
  const v = Number(n);
  if (!Number.isFinite(v)) return '$0.00';
  return `$${v.toFixed(v < 1 ? 4 : 2)}`;
}

function _saAge(iso) {
  if (!iso) return '';
  const t = Date.parse(iso);
  if (!Number.isFinite(t)) return '';
  return window.formatRelativeTime ? window.formatRelativeTime(Date.now() - t) : '';
}

// Canonical per-step sequence (#221) — must match STATIC_ADS_STEPS in
// static_ads_service.py, in real execution order (validation runs early).
const SA_STEPS = [
  { key: 'research', label: 'Researching competitor ads' },
  { key: 'validation', label: 'Scoring & winning-ad benchmark' },
  { key: 'prompt_writing', label: 'Writing the image prompt' },
  { key: 'banana_generation', label: 'Generating images' },
  { key: 'compliance', label: 'Finalizing' },
  { key: 'done', label: 'Complete' },
];

const _saStepIndex = (key) => SA_STEPS.findIndex(s => s.key === key);  // -1 if unknown

// Friendly failure text (backend classifies into state.error_message, #221);
// falls back gracefully for older rows that predate classification.
function _saFriendlyError(run) {
  return (run && run.state && run.state.error_message)
    || 'Generation failed — please try again.';
}

// Per-step progress stepper. Completed steps = check, current = spinner,
// the failed step = ✕, the rest = dim. Driven by the live polled run state.
function StaticAdsStepper({ currentStep, failedStep, status }) {
  const done = status === 'done';
  const failed = status === 'failed';
  const curIdx = done
    ? SA_STEPS.length - 1
    : failed ? _saStepIndex(failedStep) : _saStepIndex(currentStep);
  return (
    <ol className="sa-stepper">
      {SA_STEPS.map((s, i) => {
        let cls = 'pending';
        if (done || (curIdx >= 0 && i < curIdx)) cls = 'done';
        else if (curIdx >= 0 && i === curIdx) cls = failed ? 'failed' : 'active';
        return (
          <li key={s.key} className={`sa-step ${cls}`}>
            <span className="sa-step-dot">
              {cls === 'done' ? <Icon name="check" size={11} />
                : cls === 'failed' ? <Icon name="x" size={11} />
                : cls === 'active' ? <span className="sa-step-spin" aria-hidden="true" />
                : <span className="sa-step-num">{i + 1}</span>}
            </span>
            <span className="sa-step-label">{s.label}</span>
          </li>
        );
      })}
    </ol>
  );
}

// One variant tile. Image link is short-lived (15-min S3 presign); on load
// error we show a graceful "expired" placeholder rather than a broken image.
// Per-variant Save / Regenerate / Delete wired in #221 (run-scoped via runId).
function StaticAdsVariantCard({ variant, runId, onOpen, onSave, onRegenerate, onDelete, busy }) {
  const [errored, setErrored] = useSAState(false);
  const [regenOpen, setRegenOpen] = useSAState(false);
  const [regenPrompt, setRegenPrompt] = useSAState('');
  const idx = variant?.variant_idx;
  const url = variant?.image_url;
  const saved = !!variant?.saved;
  const actionsEnabled = !!runId && !busy;

  const openRegen = () => { setRegenPrompt(variant?.prompt || ''); setRegenOpen(true); };
  const confirmRegen = () => {
    const override = (regenPrompt || '').trim();
    onRegenerate && onRegenerate(runId, idx, override && override !== variant?.prompt ? override : null);
    setRegenOpen(false);
  };

  return (
    <div className={`sa-variant-card ${saved ? 'saved' : ''}`}>
      <div className="sa-variant-img">
        {url && !errored ? (
          <img
            src={url}
            alt={`Variant ${idx}`}
            loading="lazy"
            onError={() => setErrored(true)}
            onClick={() => onOpen && onOpen(url)}
          />
        ) : (
          <div className="sa-variant-missing" title={variant?.metadata?.s3_key || ''}>
            <Icon name="image" size={22} />
            <span>{errored ? 'Image link expired' : 'No image'}</span>
          </div>
        )}
        {saved && <span className="sa-variant-keeper" title="Saved as a keeper"><Icon name="check" size={11} /> Keeper</span>}
      </div>
      <div className="sa-variant-meta">
        <span className="sa-variant-idx">#{idx}</span>
        <span className="sa-variant-cost">{_saMoney(variant?.cost_usd)}</span>
        <span
          className="sa-variant-compliance"
          title="Gate B is a manual review — no automated compliance score yet"
        >
          Compliance: {variant?.compliance_score == null ? '—' : variant.compliance_score}
        </span>
      </div>
      {variant?.prompt && (
        <details className="sa-variant-prompt">
          <summary>Prompt</summary>
          <p>{variant.prompt}</p>
        </details>
      )}
      {regenOpen && (
        <div className="sa-regen-box">
          <textarea
            className="sa-regen-prompt"
            rows={3}
            value={regenPrompt}
            placeholder="Optional prompt tweak — leave as-is to reuse the original"
            onChange={(e) => setRegenPrompt(e.target.value)}
          />
          <div className="sa-regen-actions">
            <button className="btn-primary" onClick={confirmRegen} disabled={!actionsEnabled}>
              <Icon name="bolt" size={12} /> Regenerate
            </button>
            <button className="btn-secondary" onClick={() => setRegenOpen(false)}>Cancel</button>
          </div>
        </div>
      )}
      <div className="sa-variant-actions">
        <button
          className={`btn-secondary ${saved ? 'on' : ''}`}
          disabled={!actionsEnabled}
          title={saved ? 'Unmark keeper' : 'Mark as keeper'}
          onClick={() => onSave && onSave(runId, idx, !saved)}
        >
          <Icon name={saved ? 'check' : 'plus'} size={12} /> {saved ? 'Saved' : 'Save'}
        </button>
        <button
          className="btn-secondary"
          disabled={!actionsEnabled}
          title="Generate a new sibling variant"
          onClick={openRegen}
        >
          <Icon name="bolt" size={12} /> Regenerate
        </button>
        <button
          className="btn-secondary danger"
          disabled={!actionsEnabled}
          title="Delete this variant"
          onClick={() => {
            if (onDelete && window.confirm(`Delete variant #${idx}? Its image is removed too.`)) onDelete(runId, idx);
          }}
        >
          <Icon name="trash" size={12} /> Delete
        </button>
      </div>
    </div>
  );
}

function StaticAdsGallery({ variants, runId, onOpen, onSaveVariant, onRegenerateVariant, onDeleteVariant, busy }) {
  const list = Array.isArray(variants) ? variants : [];
  if (!list.length) return null;
  return (
    <div className="sa-gallery">
      {list.map(v => (
        <StaticAdsVariantCard
          key={v.variant_idx || v.metadata?.s3_key}
          variant={v}
          runId={runId}
          onOpen={onOpen}
          onSave={onSaveVariant}
          onRegenerate={onRegenerateVariant}
          onDelete={onDeleteVariant}
          busy={busy}
        />
      ))}
    </div>
  );
}

window.StaticAdsPanel = function StaticAdsPanel({
  running = false,
  status = null,
  state = null,
  activeRun = null,
  runs = [],
  brandOptions = [],
  keywordSuggestions = [],
  starting = false,
  error = null,
  onRun,
  onStop,
  onDeleteRun,
  onSaveVariant,
  onRegenerateVariant,
  onDeleteVariant,
  onRefresh,
}) {
  const [keyword, setKeyword] = useSAState('');
  const [brand, setBrand] = useSAState('');
  const [nVariants, setNVariants] = useSAState(STATIC_ADS_VARIANTS_DEFAULT);
  const [strictness, setStrictness] = useSAState('medium');  // disabled placeholder
  const [lightbox, setLightbox] = useSAState(null);
  const [lightboxError, setLightboxError] = useSAState(false);
  const [expandedRunId, setExpandedRunId] = useSAState(null);
  const [refreshing, setRefreshing] = useSAState(false);

  const handleRefresh = async () => {
    if (refreshing || !onRefresh) return;
    setRefreshing(true);
    try { await onRefresh(); } finally { setRefreshing(false); }
  };

  useSAEffect(() => { setLightboxError(false); }, [lightbox]);

  useSAEffect(() => {
    if (!lightbox) return undefined;
    const onKey = (e) => { if (e.key === 'Escape') setLightbox(null); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [lightbox]);

  const activeStatus = status || activeRun?.status || null;
  const activeState = state || activeRun?.state || {};
  const showProgress = !!activeRun && (running || ['queued', 'running', 'done', 'failed', 'cancelled'].includes(activeStatus));
  const isComplete = activeStatus === 'done';
  const indeterminate = activeStatus === 'queued' || activeStatus === 'running';
  const pct = isComplete ? 100
    : (activeStatus === 'failed' || activeStatus === 'cancelled') ? 100
    : Math.max(4, Math.round(Number(activeState?.progress || 0) * 100));

  const canRun = !!keyword.trim() && !starting && !running;
  const submit = () => {
    if (!canRun || !onRun) return;
    onRun({ keyword: keyword.trim(), brand: brand || null, nVariants: Number(nVariants) || 1, strictness });
  };

  const activeRunId = activeRun?.run_id || null;
  const historyRuns = (Array.isArray(runs) ? runs : []).filter(r => r && r.run_id !== activeRunId);

  return (
    <div className="static-ads-panel">
      {/* ---- run configuration ---- */}
      <div className="search-card sa-card">
        <div className="sc-hdr">
          <span className="sc-title"><Icon name="image" size={15} /> Static Ads</span>
          <span className="sc-sub">Generate static image-ad variants — Foreplay → scoring → Gate A → Banana</span>
          <div className="sc-actions">
            {onRefresh && (
              <button
                className="icon-btn"
                onClick={handleRefresh}
                disabled={refreshing}
                title="Refresh runs"
              >
                <Icon name="refresh" size={14} className={refreshing ? 'icon-spin' : ''} />
              </button>
            )}
          </div>
        </div>

        <div className="sa-form">
          <label className="sa-field sa-field-grow">
            <span>Keyword</span>
            <input
              type="text"
              value={keyword}
              maxLength={200}
              list={keywordSuggestions.length ? 'sa-keyword-suggestions' : undefined}
              placeholder="e.g. oil of oregano, bloating, gut health"
              onChange={(e) => setKeyword(e.target.value)}
              onKeyDown={(e) => { if (e.key === 'Enter') submit(); }}
              disabled={running}
            />
            {keywordSuggestions.length > 0 && (
              <datalist id="sa-keyword-suggestions">
                {keywordSuggestions.map(k => <option key={k} value={k} />)}
              </datalist>
            )}
          </label>

          <label className="sa-field">
            <span>Brand</span>
            <select value={brand} onChange={(e) => setBrand(e.target.value)} disabled={running}>
              <option value="">— No brand —</option>
              {brandOptions.map(b => (
                <option key={b.id || b.label} value={b.label}>{b.label}</option>
              ))}
            </select>
          </label>

          <label className="sa-field">
            <span>Variants: <strong>{nVariants}</strong></span>
            <input
              type="range"
              min={1}
              max={STATIC_ADS_VARIANTS_MAX}
              value={nVariants}
              onChange={(e) => setNVariants(Number(e.target.value))}
              disabled={running}
            />
          </label>

          {/* Strictness → Sonnet accept bar (#221). Gate A is unaffected. */}
          <label className="sa-field" title="How good a competitor ad must score to be rebuilt. Gate A is unchanged.">
            <span>Strictness</span>
            <div className="sa-strictness">
              {SA_STRICTNESS_OPTIONS.map(opt => (
                <button
                  key={opt}
                  type="button"
                  className={`sa-strictness-opt ${strictness === opt ? 'on' : ''}`}
                  disabled={running}
                  onClick={() => setStrictness(opt)}
                >
                  {opt}
                </button>
              ))}
            </div>
          </label>

          <div className="sa-actions">
            <button className="btn-primary" onClick={submit} disabled={!canRun}>
              <Icon name="image" size={14} /> {starting ? 'Starting…' : running ? 'Running…' : 'Generate'}
            </button>
          </div>
        </div>
        {error && <div className="sa-error">{error}</div>}
      </div>

      {/* ---- live progress + current run gallery ---- */}
      {showProgress && (
        <div className="search-card sa-card">
          <div className="ar-progress" style={{ background: 'transparent', padding: 0 }}>
            <div className="ar-progress-head">
              {isComplete ? (
                <span className="ar-complete-indicator" aria-hidden="true"><Icon name="check" size={10} /></span>
              ) : (
                <span className={`ar-spinner ${running ? 'spin' : ''}`} />
              )}
              <span className="ar-progress-status">{_saStatusText(activeStatus)}</span>
              <span className="ar-progress-meta">
                {activeRun?.keyword}{activeRun?.brand ? ` · ${activeRun.brand}` : ''}
                {' · '}{activeRun?.n_variants_done || 0}/{activeRun?.n_variants_requested || 0} variants
                {' · '}<strong>{_saMoney(activeRun?.cost_usd)}</strong>
              </span>
              {running && (
                <button className="btn-secondary sa-cancel-btn" onClick={() => onStop && onStop(activeRunId)}>
                  <Icon name="x" size={14} /> Cancel
                </button>
              )}
            </div>
            <StaticAdsStepper
              currentStep={activeState?.step}
              failedStep={activeState?.failed_step}
              status={activeStatus}
            />
            {indeterminate && (
              <div className="ar-progress-bar">
                <div className="ar-progress-fill" style={{ width: `${pct}%` }} />
              </div>
            )}
            {activeStatus === 'failed' && (
              <div className="sa-error" style={{ marginTop: 10 }}>
                {_saFriendlyError(activeRun)}
                {activeRun?.error && (
                  <details className="sa-error-tech">
                    <summary>Technical details</summary>
                    <p>{activeRun.error}</p>
                  </details>
                )}
              </div>
            )}
            {activeStatus !== 'failed' && activeState?.regen_error_message && (
              <div className="sa-error" style={{ marginTop: 10 }}>
                {activeState.regen_error_message}
              </div>
            )}
          </div>
          <StaticAdsGallery
            variants={activeRun?.variants}
            runId={activeRunId}
            onOpen={setLightbox}
            onSaveVariant={onSaveVariant}
            onRegenerateVariant={onRegenerateVariant}
            onDeleteVariant={onDeleteVariant}
            busy={running}
          />
        </div>
      )}

      {/* ---- run history ---- */}
      <div className="search-card sa-card">
        <div className="sc-hdr">
          <span className="sc-title">Run history</span>
          <span className="sc-sub">{historyRuns.length} prior run{historyRuns.length === 1 ? '' : 's'}</span>
        </div>
        {historyRuns.length === 0 ? (
          <div className="sa-empty">No prior runs yet. Generate your first set of variants above.</div>
        ) : (
          <div className="sa-history">
            {historyRuns.map(run => {
              const open = expandedRunId === run.run_id;
              return (
                <div key={run.run_id} className={`sa-history-row ${open ? 'open' : ''}`}>
                  <div className="sa-history-head" onClick={() => setExpandedRunId(open ? null : run.run_id)}>
                    <span className={`sa-badge ${_saStatusClass(run.status)}`}>{_saStatusText(run.status)}</span>
                    <span className="sa-history-keyword">{run.keyword || '(no keyword)'}</span>
                    {run.brand && <span className="sa-history-brand">{run.brand}</span>}
                    <span className="sa-history-dim">{run.n_variants_done || 0}/{run.n_variants_requested || 0} variants</span>
                    <span className="sa-history-dim">{_saMoney(run.cost_usd)}</span>
                    <span className="sa-history-dim">{_saAge(run.started_at)}</span>
                    <span className="sa-history-spacer" />
                    <button
                      className="icon-btn danger"
                      title="Delete run"
                      onClick={(e) => {
                        e.stopPropagation();
                        if (onDeleteRun && window.confirm('Delete this run and its variants?')) onDeleteRun(run.run_id);
                      }}
                    >
                      <Icon name="trash" size={14} />
                    </button>
                    <span className={`sa-history-chevron ${open ? 'up' : ''}`}><Icon name="chevronDown" size={14} /></span>
                  </div>
                  {open && (
                    <div className="sa-history-body">
                      {run.status === 'failed' && (
                        <div className="sa-error">
                          {_saFriendlyError(run)}
                          {run.error && (
                            <details className="sa-error-tech">
                              <summary>Technical details</summary>
                              <p>{run.error}</p>
                            </details>
                          )}
                        </div>
                      )}
                      {Array.isArray(run.variants) && run.variants.length
                        ? <StaticAdsGallery
                            variants={run.variants}
                            runId={run.run_id}
                            onOpen={setLightbox}
                            onSaveVariant={onSaveVariant}
                            onRegenerateVariant={onRegenerateVariant}
                            onDeleteVariant={onDeleteVariant}
                            busy={run.status === 'running' || run.status === 'queued'}
                          />
                        : run.status !== 'failed' && <div className="sa-empty">No variants on this run.</div>}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        )}
      </div>

      {/* ---- full-size lightbox ---- */}
      {lightbox && (
        <div className="sa-lightbox" onClick={() => setLightbox(null)}>
          <button className="sa-lightbox-close" onClick={() => setLightbox(null)}><Icon name="x" size={20} /></button>
          {lightboxError ? (
            <div className="sa-lightbox-error" onClick={(e) => e.stopPropagation()}>
              <Icon name="image" size={28} />
              <span>Image link expired — close and Refresh to reload.</span>
            </div>
          ) : (
            <img
              src={lightbox}
              alt="Variant full size"
              onClick={(e) => e.stopPropagation()}
              onError={() => setLightboxError(true)}
            />
          )}
        </div>
      )}
    </div>
  );
};
