// enhance-screen.jsx — Video → Enhance flow (talking-head in, captions/emoji/zoom/b-roll out).
// Self-contained: upload → analyze → review/edit plan → render → output.
// Reuses the AutoCut shell + CSS design tokens. Registered as a global component.

const TXT_ENH = {
  vi: {
    title: "Làm đẹp video người nói",
    subtitle: "Tải video lên — AI tự thêm chữ nhấn, emoji, zoom và b-roll minh hoạ.",
    pickVideo: "Chọn video (.mp4, .mov, .webm)",
    dropHint: "Kéo thả video vào đây hoặc bấm để chọn",
    language: "Ngôn ngữ thoại",
    analyze: "Phân tích video",
    analyzing: "Đang phân tích…",
    probing: "Đang đọc thông số video…",
    uploading: "Đang tải video lên…",
    reviewTitle: "Xem & chỉnh kế hoạch hiệu ứng",
    reviewHint: "Sửa, xoá hoặc thêm hiệu ứng trước khi render.",
    keywords: "Chữ nhấn (keyword)",
    emojis: "Emoji",
    zooms: "Zoom",
    broll: "B-roll (hình minh hoạ)",
    graphics: "Scene giải thích (Graphic)",
    graphicDesc: "Mô tả visual",
    render: "Render video",
    rendering: "Đang render…",
    fetching: "Đang tải hình/clip b-roll…",
    generatingGraphics: "Đang tạo scene giải thích…",
    done: "Hoàn tất!",
    download: "Tải video",
    newJob: "Làm video khác",
    add: "Thêm",
    empty: "Chưa có",
    text: "Chữ", start: "Bắt đầu", end: "Kết thúc", style: "Kiểu", size: "Cỡ",
    pos: "Vị trí", anim: "Hiệu ứng", scale: "Mức zoom", source: "Nguồn",
    query: "Mô tả/từ khoá", transition: "Chuyển cảnh", emoji: "Emoji",
    sec: "giây", failed: "Thất bại",
  },
  en: {
    title: "Enhance talking-head video",
    subtitle: "Upload a video — AI adds keyword pop-ups, emojis, zooms and b-roll.",
    pickVideo: "Choose a video (.mp4, .mov, .webm)",
    dropHint: "Drag a video here or click to choose",
    language: "Spoken language",
    analyze: "Analyze video",
    analyzing: "Analyzing…",
    probing: "Reading video metadata…",
    uploading: "Uploading video…",
    reviewTitle: "Review & edit the effect plan",
    reviewHint: "Edit, delete or add cues before rendering.",
    keywords: "Keyword pop-ups",
    emojis: "Emojis",
    zooms: "Zooms",
    broll: "B-roll",
    graphics: "Graphic scenes",
    graphicDesc: "Visual description",
    render: "Render video",
    rendering: "Rendering…",
    fetching: "Fetching b-roll assets…",
    generatingGraphics: "Generating graphic scenes…",
    done: "Done!",
    download: "Download",
    newJob: "New video",
    add: "Add",
    empty: "None yet",
    text: "Text", start: "Start", end: "End", style: "Style", size: "Size",
    pos: "Pos", anim: "Anim", scale: "Zoom", source: "Source",
    query: "Query/prompt", transition: "Transition", emoji: "Emoji",
    sec: "s", failed: "Failed",
  },
};

const ENH_POLL_MS = 2000;
const KW_STYLE_OPTS = ["default", "money", "warning"];
const KW_SIZE_OPTS = ["s", "m", "l", "xl"];
const KW_POS_OPTS = ["top", "bottom"];
const EMOJI_ANIM_OPTS = ["pop", "bounce", "float"];
const BROLL_SOURCE_OPTS = ["unsplash", "imagen", "veo"];
const BROLL_TRANS_OPTS = ["zoom", "whip", "fade"];

// ── small styled primitives ──────────────────────────────────────────────
const enhInput = {
  background: "var(--bg-1)", border: "1px solid var(--line)", color: "var(--fg-0)",
  borderRadius: "var(--radius)", padding: "6px 8px", fontSize: 12.5,
  fontFamily: "var(--font-sans)", width: "100%", boxSizing: "border-box",
};
const enhBtn = (primary) => ({
  padding: "10px 18px", fontSize: 13.5, fontWeight: 600,
  borderRadius: "var(--radius)", cursor: "pointer", border: "none",
  background: primary ? "var(--accent)" : "var(--bg-3)",
  color: primary ? "var(--accent-fg)" : "var(--fg-1)",
});

function EnhField({ label, children }) {
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 3, flex: 1, minWidth: 0 }}>
      <span style={{ fontSize: 10, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: ".05em" }}>{label}</span>
      {children}
    </label>
  );
}

function EnhSelect({ value, options, onChange }) {
  return (
    <select value={value} onChange={(e) => onChange(e.target.value)} style={{ ...enhInput, cursor: "pointer" }}>
      {options.map((o) => <option key={o} value={o}>{o}</option>)}
    </select>
  );
}

function EnhNum({ value, onChange, step }) {
  return (
    <input type="number" step={step || 0.1} value={value}
      onChange={(e) => onChange(parseFloat(e.target.value))} style={enhInput} />
  );
}

// ── cue row (a flex row of fields + delete) ────────────────────────────────
function CueRow({ children, onDelete }) {
  return (
    <div style={{
      display: "flex", gap: 8, alignItems: "flex-end",
      padding: "8px 10px", background: "var(--bg-2)",
      border: "1px solid var(--line-soft)", borderRadius: "var(--radius)",
    }}>
      {children}
      <button onClick={onDelete} title="Delete" style={{
        flex: "0 0 auto", width: 28, height: 28, borderRadius: "var(--radius)",
        border: "1px solid var(--line)", background: "var(--bg-1)",
        color: "var(--err)", cursor: "pointer", fontSize: 14, lineHeight: 1,
      }}>×</button>
    </div>
  );
}

function CueSection({ title, count, onAdd, children }) {
  return (
    <section style={{ marginBottom: 18 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
        <h3 style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-0)", margin: 0 }}>
          {title} <span style={{ color: "var(--fg-3)", fontWeight: 400 }}>({count})</span>
        </h3>
        <button onClick={onAdd} style={{
          padding: "4px 10px", fontSize: 11.5, fontWeight: 600, cursor: "pointer",
          borderRadius: "var(--radius)", border: "1px solid var(--accent-line)",
          background: "var(--accent-soft)", color: "var(--accent)",
        }}>+ {title}</button>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>{children}</div>
    </section>
  );
}

function EnhanceScreen({ uiLang }) {
  const T = TXT_ENH[uiLang] || TXT_ENH.vi;
  const [phase, setPhase] = React.useState("upload"); // upload|processing|review|rendering|done|error
  const [file, setFile] = React.useState(null);
  const [language, setLanguage] = React.useState(uiLang === "vi" ? "Vietnamese" : "English");
  const [jobId, setJobId] = React.useState(null);
  const [status, setStatus] = React.useState(null);
  const [plan, setPlan] = React.useState(null);
  const [meta, setMeta] = React.useState(null);
  const [videoUrl, setVideoUrl] = React.useState(null);
  const [error, setError] = React.useState(null);
  const fileInputRef = React.useRef(null);

  // ── polling ──────────────────────────────────────────────────────────────
  React.useEffect(() => {
    if (!jobId || (phase !== "processing" && phase !== "rendering")) return;
    let alive = true;
    const tick = async () => {
      try {
        const res = await fetch(`/api/enhance/${jobId}/status`);
        if (!res.ok) throw new Error(`status ${res.status}`);
        const s = await res.json();
        if (!alive) return;
        setStatus(s.status);
        if (s.meta) setMeta(s.meta);
        if (s.status === "AWAITING_REVIEW") {
          setPlan(s.plan || { keywords: [], emojis: [], zooms: [], broll: [], graphics: [] });
          setPhase("review");
          return;
        }
        if (s.status === "COMPLETED") {
          setVideoUrl((s.video_url || `/files/${jobId}/output.mp4`) + `?t=${Date.now()}`);
          setPhase("done");
          return;
        }
        if (s.status === "FAILED") { setError(s.error || "Failed"); setPhase("error"); return; }
        setTimeout(tick, ENH_POLL_MS);
      } catch (e) {
        if (alive) setTimeout(tick, ENH_POLL_MS);
      }
    };
    const id = setTimeout(tick, 400);
    return () => { alive = false; clearTimeout(id); };
  }, [jobId, phase]);

  // ── actions ────────────────────────────────────────────────────────────
  const startAnalyze = async () => {
    if (!file) return;
    setError(null); setPhase("processing"); setStatus("PENDING");
    try {
      const fd = new FormData();
      fd.append("file", file);
      fd.append("language", language);
      const res = await fetch("/api/enhance", { method: "POST", body: fd });
      if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
      const data = await res.json();
      setJobId(data.job_id);
    } catch (e) { setError(String(e.message || e)); setPhase("error"); }
  };

  const startRender = async () => {
    try {
      const pr = await fetch(`/api/enhance/${jobId}/plan`, {
        method: "PATCH", headers: { "Content-Type": "application/json" },
        body: JSON.stringify(plan),
      });
      if (!pr.ok) throw new Error(`plan ${pr.status}: ${await pr.text()}`);
      const cr = await fetch(`/api/enhance/${jobId}/continue`, { method: "POST" });
      if (!cr.ok) throw new Error(`continue ${cr.status}`);
      setStatus("FETCHING_ASSETS"); setPhase("rendering");
    } catch (e) { setError(String(e.message || e)); setPhase("error"); }
  };

  const reset = () => {
    setPhase("upload"); setFile(null); setJobId(null); setStatus(null);
    setPlan(null); setMeta(null); setVideoUrl(null); setError(null);
  };

  // ── plan editing helpers (immutable) ──────────────────────────────────────
  const updateCue = (key, idx, field, val) => setPlan((p) => ({
    ...p, [key]: p[key].map((c, i) => i === idx ? { ...c, [field]: val } : c),
  }));
  const deleteCue = (key, idx) => setPlan((p) => ({ ...p, [key]: p[key].filter((_, i) => i !== idx) }));
  const addCue = (key, blank) => setPlan((p) => ({ ...p, [key]: [...(p[key] || []), blank] }));

  const wrap = { maxWidth: 880, margin: "0 auto", padding: "0 24px" };

  // ── UPLOAD ────────────────────────────────────────────────────────────────
  if (phase === "upload") {
    return (
      <div style={wrap}>
        <h1 style={{ fontSize: 26, fontWeight: 700, color: "var(--fg-0)", margin: "8px 0 4px" }}>{T.title}</h1>
        <p style={{ color: "var(--fg-2)", fontSize: 14, marginTop: 0, marginBottom: 22 }}>{T.subtitle}</p>

        <div
          onClick={() => fileInputRef.current && fileInputRef.current.click()}
          onDragOver={(e) => e.preventDefault()}
          onDrop={(e) => { e.preventDefault(); const f = e.dataTransfer.files[0]; if (f) setFile(f); }}
          style={{
            border: "1.5px dashed var(--line-strong)", borderRadius: "var(--radius-lg)",
            padding: "40px 24px", textAlign: "center", cursor: "pointer",
            background: "var(--bg-1)", transition: "border-color .15s",
          }}
        >
          <input ref={fileInputRef} type="file" accept="video/mp4,video/quicktime,video/webm,video/x-matroska"
            style={{ display: "none" }} onChange={(e) => setFile(e.target.files[0] || null)} />
          <div style={{ fontSize: 32, marginBottom: 8 }}>🎬</div>
          {file ? (
            <div style={{ color: "var(--fg-0)", fontSize: 14, fontWeight: 600 }}>{file.name}
              <div style={{ color: "var(--fg-3)", fontSize: 12, fontWeight: 400, marginTop: 2 }}>
                {(file.size / (1024 * 1024)).toFixed(1)} MB
              </div>
            </div>
          ) : (
            <div style={{ color: "var(--fg-2)", fontSize: 13.5 }}>{T.dropHint}</div>
          )}
        </div>

        <div style={{ display: "flex", gap: 14, alignItems: "flex-end", marginTop: 18 }}>
          <div style={{ width: 200 }}>
            <EnhField label={T.language}>
              <EnhSelect value={language} options={["Vietnamese", "English"]} onChange={setLanguage} />
            </EnhField>
          </div>
          <div style={{ flex: 1 }} />
          <button disabled={!file} onClick={startAnalyze}
            style={{ ...enhBtn(true), opacity: file ? 1 : 0.5, cursor: file ? "pointer" : "not-allowed" }}>
            {T.analyze} →
          </button>
        </div>
      </div>
    );
  }

  // ── PROCESSING / RENDERING ──────────────────────────────────────────────
  if (phase === "processing" || phase === "rendering") {
    const labelMap = {
      PENDING: T.uploading, PROBING: T.probing, ANALYZING: T.analyzing,
      FETCHING_ASSETS: T.fetching,
      GENERATING_GRAPHICS: T.generatingGraphics,
      RENDERING: T.rendering,
    };
    return (
      <div style={{ ...wrap, textAlign: "center", paddingTop: 60 }}>
        <div className="enh-spin" style={{
          width: 40, height: 40, margin: "0 auto 20px",
          border: "3px solid var(--line)", borderTopColor: "var(--accent)",
          borderRadius: "50%", animation: "enhspin 0.8s linear infinite",
        }} />
        <div style={{ fontSize: 16, fontWeight: 600, color: "var(--fg-0)" }}>
          {labelMap[status] || T.analyzing}
        </div>
        {meta && (
          <div style={{ color: "var(--fg-3)", fontSize: 12.5, marginTop: 8, fontFamily: "var(--font-mono)" }}>
            {meta.width}×{meta.height} · {meta.fps}fps · {Math.round(meta.duration_seconds)}{T.sec}
          </div>
        )}
        <style>{`@keyframes enhspin{to{transform:rotate(360deg)}}`}</style>
      </div>
    );
  }

  // ── DONE ────────────────────────────────────────────────────────────────
  if (phase === "done") {
    return (
      <div style={{ ...wrap, textAlign: "center" }}>
        <h1 style={{ fontSize: 24, fontWeight: 700, color: "var(--fg-0)", margin: "8px 0 16px" }}>✅ {T.done}</h1>
        <video src={videoUrl} controls style={{
          maxHeight: "62vh", maxWidth: "100%", borderRadius: "var(--radius-lg)",
          border: "1px solid var(--line)", background: "#000",
        }} />
        <div style={{ display: "flex", gap: 12, justifyContent: "center", marginTop: 18 }}>
          <a href={videoUrl} download style={{ ...enhBtn(true), textDecoration: "none" }}>↓ {T.download}</a>
          <button onClick={reset} style={enhBtn(false)}>{T.newJob}</button>
        </div>
      </div>
    );
  }

  // ── ERROR ────────────────────────────────────────────────────────────────
  if (phase === "error") {
    return (
      <div style={{ ...wrap, textAlign: "center", paddingTop: 40 }}>
        <div style={{ fontSize: 15, fontWeight: 600, color: "var(--err)" }}>⚠ {T.failed}</div>
        <pre style={{
          textAlign: "left", whiteSpace: "pre-wrap", color: "var(--fg-2)", fontSize: 12,
          background: "var(--bg-1)", border: "1px solid var(--line)", borderRadius: "var(--radius)",
          padding: 12, marginTop: 12, maxHeight: 240, overflow: "auto",
        }}>{error}</pre>
        <button onClick={reset} style={{ ...enhBtn(false), marginTop: 16 }}>{T.newJob}</button>
      </div>
    );
  }

  // ── REVIEW (plan editor) ──────────────────────────────────────────────────
  const p = plan || { keywords: [], emojis: [], zooms: [], broll: [], graphics: [] };
  return (
    <div style={wrap}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }}>
        <h1 style={{ fontSize: 22, fontWeight: 700, color: "var(--fg-0)", margin: "8px 0 0" }}>{T.reviewTitle}</h1>
        <button onClick={startRender} style={enhBtn(true)}>{T.render} →</button>
      </div>
      <p style={{ color: "var(--fg-2)", fontSize: 13, marginTop: 4, marginBottom: 20 }}>{T.reviewHint}</p>

      <CueSection title={T.keywords} count={p.keywords.length}
        onAdd={() => addCue("keywords", { text: "", start: 0, end: 2, style: "default", size: "m", pos: "top" })}>
        {p.keywords.length === 0 && <Empty T={T} />}
        {p.keywords.map((c, i) => (
          <CueRow key={i} onDelete={() => deleteCue("keywords", i)}>
            <div style={{ flex: 2 }}><EnhField label={T.text}><input value={c.text} onChange={(e) => updateCue("keywords", i, "text", e.target.value)} style={enhInput} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.start}><EnhNum value={c.start} onChange={(v) => updateCue("keywords", i, "start", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.end}><EnhNum value={c.end} onChange={(v) => updateCue("keywords", i, "end", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.style}><EnhSelect value={c.style} options={KW_STYLE_OPTS} onChange={(v) => updateCue("keywords", i, "style", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.size}><EnhSelect value={c.size} options={KW_SIZE_OPTS} onChange={(v) => updateCue("keywords", i, "size", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.pos}><EnhSelect value={c.pos} options={KW_POS_OPTS} onChange={(v) => updateCue("keywords", i, "pos", v)} /></EnhField></div>
          </CueRow>
        ))}
      </CueSection>

      <CueSection title={T.emojis} count={p.emojis.length}
        onAdd={() => addCue("emojis", { emoji: "🔥", start: 0, anim: "pop", x: 0.85, y: 0.18 })}>
        {p.emojis.length === 0 && <Empty T={T} />}
        {p.emojis.map((c, i) => (
          <CueRow key={i} onDelete={() => deleteCue("emojis", i)}>
            <div style={{ flex: 1 }}><EnhField label={T.emoji}><input value={c.emoji} onChange={(e) => updateCue("emojis", i, "emoji", e.target.value)} style={{ ...enhInput, textAlign: "center", fontSize: 18 }} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.start}><EnhNum value={c.start} onChange={(v) => updateCue("emojis", i, "start", v)} /></EnhField></div>
            <div style={{ flex: 2 }}><EnhField label={T.anim}><EnhSelect value={c.anim} options={EMOJI_ANIM_OPTS} onChange={(v) => updateCue("emojis", i, "anim", v)} /></EnhField></div>
          </CueRow>
        ))}
      </CueSection>

      <CueSection title={T.zooms} count={p.zooms.length}
        onAdd={() => addCue("zooms", { start: 0, end: 2, scale: 1.15, focus_x: 0.5, focus_y: 0.4 })}>
        {p.zooms.length === 0 && <Empty T={T} />}
        {p.zooms.map((c, i) => (
          <CueRow key={i} onDelete={() => deleteCue("zooms", i)}>
            <div style={{ flex: 1 }}><EnhField label={T.start}><EnhNum value={c.start} onChange={(v) => updateCue("zooms", i, "start", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.end}><EnhNum value={c.end} onChange={(v) => updateCue("zooms", i, "end", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.scale}><EnhNum step={0.01} value={c.scale} onChange={(v) => updateCue("zooms", i, "scale", v)} /></EnhField></div>
          </CueRow>
        ))}
      </CueSection>

      <CueSection title={T.broll} count={p.broll.length}
        onAdd={() => addCue("broll", { start: 0, end: 8, source: "unsplash", query: "", transition: "zoom" })}>
        {p.broll.length === 0 && <Empty T={T} />}
        {p.broll.map((c, i) => (
          <CueRow key={i} onDelete={() => deleteCue("broll", i)}>
            <div style={{ flex: 3 }}><EnhField label={T.query}><input value={c.query} onChange={(e) => updateCue("broll", i, "query", e.target.value)} style={enhInput} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.start}><EnhNum value={c.start} onChange={(v) => updateCue("broll", i, "start", v)} /></EnhField></div>
            <div style={{ flex: 1 }}><EnhField label={T.end}><EnhNum value={c.end} onChange={(v) => updateCue("broll", i, "end", v)} /></EnhField></div>
            <div style={{ flex: 1.4 }}><EnhField label={T.source}><EnhSelect value={c.source} options={BROLL_SOURCE_OPTS} onChange={(v) => updateCue("broll", i, "source", v)} /></EnhField></div>
            <div style={{ flex: 1.2 }}><EnhField label={T.transition}><EnhSelect value={c.transition} options={BROLL_TRANS_OPTS} onChange={(v) => updateCue("broll", i, "transition", v)} /></EnhField></div>
          </CueRow>
        ))}
      </CueSection>

      <CueSection title={T.graphics} count={(p.graphics || []).length}
        onAdd={() => addCue("graphics", { start: 0, end: 9, description: "", scene_tsx: null })}>
        {(p.graphics || []).length === 0 && <Empty T={T} />}
        {(p.graphics || []).map((c, i) => (
          <CueRow key={i} onDelete={() => deleteCue("graphics", i)}>
            <div style={{ flex: 1 }}>
              <EnhField label={T.start}><EnhNum value={c.start} onChange={(v) => updateCue("graphics", i, "start", v)} /></EnhField>
            </div>
            <div style={{ flex: 1 }}>
              <EnhField label={T.end}><EnhNum value={c.end} onChange={(v) => updateCue("graphics", i, "end", v)} /></EnhField>
            </div>
            <div style={{ flex: 6 }}>
              <EnhField label={T.graphicDesc}>
                <textarea
                  rows={2}
                  value={c.description}
                  onChange={(e) => updateCue("graphics", i, "description", e.target.value)}
                  placeholder="Dark navy background with grid, 💰 springs in at 0s → red arrow → 🏦 at 5s…"
                  style={{
                    ...enhInput, resize: "vertical", lineHeight: 1.5,
                    color: c.scene_tsx ? "var(--ok)" : "var(--fg-0)",
                  }}
                />
              </EnhField>
            </div>
            {c.scene_tsx && (
              <div style={{ flex: "0 0 auto", alignSelf: "flex-end", padding: "0 2px 6px" }}>
                <span style={{ fontSize: 11, color: "var(--ok)", fontWeight: 600 }}>✓ OK</span>
              </div>
            )}
          </CueRow>
        ))}
      </CueSection>

      <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 8, marginBottom: 40 }}>
        <button onClick={startRender} style={enhBtn(true)}>{T.render} →</button>
      </div>
    </div>
  );
}

function Empty({ T }) {
  return <div style={{ color: "var(--fg-4)", fontSize: 12, fontStyle: "italic", padding: "2px 4px" }}>{T.empty}</div>;
}
