/* Review (timeline manifest + clip preview + export trigger).
   Live mode: when projectId is set, fetches the real timeline manifest +
   asset list from the API and previews completed clips inline. */

const ScreenReview = ({ data, batchId, projectId }) => {
  const { jobs, shots } = data;

  const [timeline, setTimeline] = React.useState(null);
  const [assets, setAssets]     = React.useState([]);
  const [exporting, setExporting] = React.useState(false);
  const [exportInfo, setExportInfo] = React.useState(null);
  const [error, setError]       = React.useState(null);
  const [captioning, setCaptioning] = React.useState(false);
  const [captions, setCaptions] = React.useState(null);

  const onGenerateCaptions = async () => {
    if (!projectId) return;
    setCaptioning(true); setError(null);
    try {
      const info = await window.CinematonAPI.generateSubtitles(projectId);
      setCaptions(info);
    } catch (err) { setError(err); }
    finally { setCaptioning(false); }
  };

  // Pull live timeline + assets when in live mode.
  React.useEffect(() => {
    if (!projectId || !window.CinematonAPI) return;
    let cancelled = false;
    Promise.all([
      window.CinematonAPI.timeline(projectId).catch(() => null),
      window.CinematonAPI.listAssets(projectId, { type: 'video' }).catch(() => []),
    ]).then(([t, a]) => {
      if (cancelled) return;
      setTimeline(t);
      setAssets(Array.isArray(a) ? a : []);
    });
    return () => { cancelled = true; };
  }, [projectId, batchId]); // re-fetch when a new batch lands

  const totalSeconds =
    timeline?.total_runtime_seconds ?? shots.reduce((a, s) => a + s.dur, 0);

  const onExport = async () => {
    if (!projectId) return;
    setExporting(true); setError(null);
    try {
      const info = await window.CinematonAPI.exportProject(projectId);
      setExportInfo(info);
    } catch (err) { setError(err); }
    finally { setExporting(false); }
  };

  const completed = jobs.filter((j) => j.status === 'complete' && j.asset);
  const showLivePreview = projectId && (timeline || assets.length > 0);

  return (
    <div className="page" style={{ display: 'grid', gridTemplateRows: 'auto 1fr', height: '100%' }}>
      <PageHeader title="Review · Timeline Manifest" sub={`Stage 08 / 09 · ${formatTime(totalSeconds)} assembly`}>
        {projectId && <span className="tag accent">live</span>}
        <button className="btn ghost" onClick={onExport} disabled={!projectId || exporting}>
          {exporting ? 'Bundling…' : 'Export package'}
        </button>
        <button className="btn primary" onClick={onGenerateCaptions} disabled={!projectId || captioning}>
          {captioning ? 'Generating…' : 'Generate captions'}
        </button>
      </PageHeader>

      <div className="scroll" style={{ padding: 22 }}>
        {/* Timeline strip */}
        <div className="card" style={{ marginBottom: 18 }}>
          <div className="card-title">
            Timeline · {formatTime(totalSeconds)} cut
            {timeline && <span className="dim mono" style={{ marginLeft: 10, fontSize: 10 }}>
              {timeline.tracks?.[0]?.clips?.length ?? 0} clips
            </span>}
          </div>
          <div style={{ display: 'flex', height: 48, background: 'var(--bg-inset)', borderRadius: 3, overflow: 'hidden', border: '1px solid var(--line)' }}>
            {(timeline?.tracks?.[0]?.clips ?? shots.map((s) => ({ shot_id: s.id, duration: s.dur }))).map((clip, i, arr) => {
              const id  = clip.shot_id || clip.id || String(i);
              const dur = clip.duration ?? clip.dur ?? 5;
              const hasAsset = clip.asset_id && !String(clip.asset_id).startsWith('pending_');
              return (
                <div key={id} title={`${id} · ${dur}s${hasAsset ? ' · rendered' : ''}`}
                  style={{
                    flex: dur,
                    borderRight: i < arr.length - 1 ? '1px solid var(--bg-inset)' : 'none',
                    background: hasAsset ? 'var(--accent)' : (i % 2 === 0 ? 'var(--bg-2)' : 'var(--bg-3)'),
                    opacity: hasAsset ? 0.85 : 1,
                    position: 'relative', cursor: 'pointer',
                  }}>
                  <div className="mono" style={{ position: 'absolute', top: 4, left: 4, fontSize: 9, color: hasAsset ? 'var(--accent-ink)' : 'var(--fg-faint)' }}>
                    {String(id).replace('sh_', '').slice(0, 6)}
                  </div>
                  <div className="mono" style={{ position: 'absolute', bottom: 4, right: 4, fontSize: 9, color: hasAsset ? 'var(--accent-ink)' : 'var(--fg-faint)' }}>{dur}s</div>
                </div>
              );
            })}
          </div>
          <div className="row" style={{ marginTop: 8, fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-faint)' }}>
            <span>0:00</span>
            <span style={{ flex: 1, textAlign: 'center' }}>{formatTime(totalSeconds / 2)}</span>
            <span>{formatTime(totalSeconds)}</span>
          </div>
        </div>

        {/* Live clip preview grid */}
        {showLivePreview && assets.length > 0 && (
          <div className="card" style={{ marginBottom: 18 }}>
            <div className="card-title">Rendered clips · {assets.length} of {timeline?.tracks?.[0]?.clips?.length ?? '?'}</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 10 }}>
              {assets.map((a) => (
                <div key={a.asset_id} style={{ background: 'var(--bg-inset)', border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
                  <div style={{ background: 'var(--bg-3)', aspectRatio: '16/9', display: 'grid', placeItems: 'center' }}>
                    {a.storage_uri.startsWith('mock://') ? (
                      <span className="mono dim" style={{ fontSize: 10 }}>MOCK · {a.linked_entity_id}</span>
                    ) : a.storage_uri.startsWith('file://') ? (
                      <span className="mono dim" style={{ fontSize: 10 }}>local file · {a.linked_entity_id}</span>
                    ) : (
                      <video src={a.storage_uri} controls preload="metadata" style={{ width: '100%', height: '100%', objectFit: 'cover' }}/>
                    )}
                  </div>
                  <div style={{ padding: '8px 10px', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                    <span className="mono" style={{ fontSize: 10.5, color: 'var(--fg)' }}>{a.linked_entity_id}</span>
                    <span className="mono dim" style={{ fontSize: 10 }}>{a.provider.replace(/_/g, ' ')}</span>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {/* Captions output */}
        {captions && (
          <div className="card" style={{ marginBottom: 18, borderColor: 'var(--accent-dim)' }}>
            <div className="card-title">Captions generated · {captions.line_count} line{captions.line_count === 1 ? '' : 's'}</div>
            <div className="row gap-sm" style={{ marginTop: 10 }}>
              <a className="btn primary" href={captions.srt_url}>Download .srt</a>
              <a className="btn ghost" href={captions.vtt_url}>Download .vtt</a>
            </div>
          </div>
        )}

        {/* Export status */}
        {exportInfo && (
          <div className="card" style={{ marginBottom: 18, borderColor: 'var(--accent-dim)' }}>
            <div className="card-title">Export bundled</div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--fg)', marginBottom: 8, wordBreak: 'break-all' }}>
              {exportInfo.zip_path}
            </div>
            <div className="dim mono" style={{ fontSize: 10, marginBottom: 12 }}>SHA256: {exportInfo.sha256.slice(0, 24)}…</div>
            <a className="btn primary" href={exportInfo.download_url}>Download .zip</a>
          </div>
        )}

        {error && (
          <div className="card" style={{ borderColor: 'oklch(0.4 0.1 25)', color: 'var(--bad)' }}>
            <div className="card-title" style={{ color: 'var(--bad)' }}>Error</div>
            {error.message || String(error)}
          </div>
        )}

        {/* Empty state — only when not in live mode, or live mode has no assets yet */}
        {!showLivePreview && completed.length === 0 && (
          <div className="card" style={{ padding: '44px 22px 38px', textAlign: 'center' }}>
            <div className="maton-empty">
              <svg width="120" height="100" viewBox="-110 -100 220 200" aria-hidden="true">
                <rect x="-78" y="-50" width="156" height="100" rx="6" fill="none" stroke="var(--fg)" strokeWidth="2"/>
                <line x1="-78" y1="0" x2="78" y2="0" stroke="#5e9bff" strokeWidth="2.5"/>
                <circle cx="-72" cy="0" r="3.5" fill="var(--fg)"/>
                <circle cx="72" cy="0" r="3.5" fill="var(--fg)"/>
                <circle r="9" fill="#5e9bff">
                  <animate attributeName="cx" values="-72; 14; 72; 14; -72" dur="5s" repeatCount="indefinite"/>
                  <animate attributeName="r" values="3.5; 9; 3.5; 9; 3.5" dur="5s" repeatCount="indefinite"/>
                  <animate attributeName="opacity" values="0.5; 1; 0.5; 1; 0.5" dur="5s" repeatCount="indefinite"/>
                </circle>
              </svg>
            </div>
            <div className="mono dim" style={{ fontSize: 11, marginBottom: 8, marginTop: 22 }}>EXPORT PACKAGE</div>
            <h3 className="serif" style={{ fontSize: 22, margin: 0 }}>Render queue is still working</h3>
            <p className="muted" style={{ maxWidth: 460, margin: '10px auto 0' }}>
              Once the render queue completes, you'll be able to export the full project package: screenplay, prompts, cost approval record, media manifest, timeline manifest, and subtitles.
            </p>
          </div>
        )}
      </div>
    </div>
  );
};

function formatTime(seconds) {
  const s = Math.max(0, Math.round(seconds || 0));
  const m = Math.floor(s / 60);
  const r = s % 60;
  return `${m}:${String(r).padStart(2, '0')}`;
}

window.ScreenReview = ScreenReview;
