/* global React, ReactDOM, window */
// Main App — composes screens, wires test cases TC-01/02/03/04/07/11.

const { useState, useEffect, useMemo, useRef } = React;
const {
  ADS, BRAND, INITIAL_TASKS, INITIAL_ITERATIONS, REC_TEMPLATES,
  PULSE_ALERTS, PLAYGROUND_DEMOS, IMAGE_AD_PROJECTS, BRANDS,
  Sidebar, TopBar, Radar, DetailDrawer, ActionModal, Variants,
  TasksPanel, RationaleDrawer, Icon, IterationHistory, FeedbackModal,
  Pulse, Playground, ImageAds, Overview, BrandsList,
  TweaksPanel, useTweaks, TweakSection, TweakRadio,
} = window;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "warm"
}/*EDITMODE-END*/;

function App() {
  // Subscribe to language changes so the App re-renders on switch — the
  // many derived strings below (screenLabel, breadcrumb, toasts via window.t)
  // are computed inline at render time and need this re-render to refresh.
  window.useLang();

  const [tw, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // First-visit onboarding (localStorage-backed; fires once per browser).
  const [onboardingOpen, setOnboardingOpen] = window.useOnboarding ? window.useOnboarding() : [false, () => {}];

  const [screen, setScreen] = useState("radar"); // radar | variants
  const [tasks, setTasks] = useState(INITIAL_TASKS);
  const [iterationsByAd, setIterationsByAd] = useState(INITIAL_ITERATIONS);
  const [pausedAds, setPausedAds] = useState(new Set());
  const [scaledAds, setScaledAds] = useState(new Set());

  const [selectedAdId, setSelectedAdId] = useState(null);
  const [drawerOpen, setDrawerOpen] = useState(false);

  const [modalState, setModalState] = useState({ open: false, adId: null, recIds: [] });

  const [tasksPopOpen, setTasksPopOpen] = useState(false);
  const [rationaleOpen, setRationaleOpen] = useState(false);

  const [currentVariantTaskId, setCurrentVariantTaskId] = useState(null);
  const [toasts, setToasts] = useState([]);

  // M4 (A-4): feedback modal state
  const [feedbackState, setFeedbackState] = useState({ open: false, rec: null, ad: null, done: null });

  // Round 3: extended platform screens
  const [focusedAlertId, setFocusedAlertId] = useState(null);
  const [activeBrandId, setActiveBrandId] = useState("lipsum");
  const activeBrand = (BRANDS || []).find(b => b.id === activeBrandId);

  // Round 4 (Raya): ads created via the Playground's Raya conversational
  // panel get prepended to the Radar list with a "just created" highlight.
  // createdAds: { id, code, headline, headlineZh, sub, subZh, prompt, _created: timestamp, _highlight: boolean }
  const [createdAds, setCreatedAds] = useState([]);
  // newAdScrollTrigger increments every time we push a new ad so Radar
  // can scroll it into view (a counter, not a boolean, so successive
  // creates each trigger a scroll even to the same row).
  const [newAdScrollTrigger, setNewAdScrollTrigger] = useState(0);
  // Modal state for the "+ 创建广告创意" entry on Radar / Overview.
  const [createModalOpen, setCreateModalOpen] = useState(false);
  // Pre-filled prompt scaffold passed to Raya when user enters Playground
  // via the "Let Raya help" path on the create modal.
  const [rayaScaffoldPrompt, setRayaScaffoldPrompt] = useState("");

  // Build alertsByAd index for Radar row indicator
  const alertsByAd = useMemo(() => {
    const m = {};
    (PULSE_ALERTS || []).forEach(a => {
      if (!m[a.adId]) m[a.adId] = [];
      m[a.adId].push(a);
    });
    return m;
  }, []);

  useEffect(() => {
    document.documentElement.dataset.theme = tw.theme || "warm";
  }, [tw.theme]);

  const ad = ADS.find(a => a.id === selectedAdId);
  const runningTasksByAd = useMemo(() => {
    const m = {};
    tasks.forEach(tt => { if (tt.status === "running") m[tt.adId] = (m[tt.adId] || 0) + 1; });
    return m;
  }, [tasks]);
  const completedTasksByAd = useMemo(() => {
    const m = {};
    tasks.forEach(tt => { if (tt.status === "completed") (m[tt.adId] = m[tt.adId] || []).push(tt); });
    return m;
  }, [tasks]);
  const runningCount = tasks.filter(x => x.status === "running").length;

  function pushToast(text, kind) {
    const id = "t" + Math.random().toString(36).slice(2, 9);
    setToasts(cur => [...cur, { id, text, kind }]);
    setTimeout(() => setToasts(cur => cur.filter(x => x.id !== id)), 4500);
  }
  // Expose a global pushToast so non-prop-drilled screens (Playground variant
  // buttons, future deep-link handlers) can drop a toast without threading
  // callbacks through.
  window.__pushToast = pushToast;

  const [drawerInitialTab, setDrawerInitialTab] = useState("airec");
  // openSeq increments on every openAd call so the DetailDrawer's effect
  // re-fires even when the same ad + same tab are re-opened back-to-back.
  // Fixes the case where clicking «为什么?» twice on the same row would
  // not re-snap the drawer to Performance because none of the other deps
  // changed.
  const [drawerOpenSeq, setDrawerOpenSeq] = useState(0);
  function openAd(id, tab) {
    setSelectedAdId(id);
    setDrawerInitialTab(tab || "airec");
    setDrawerOpenSeq(s => s + 1);
    setDrawerOpen(true);
  }
  function closeDrawer() { setDrawerOpen(false); }

  // ===== Pause / Scale inline actions =====
  function onPauseAd(adId) {
    setPausedAds(s => new Set([...s, adId]));
    const a = ADS.find(x => x.id === adId);
    const tt = window.t;
    pushToast(tt(`Paused ${a?.code} on Meta Ads Manager · ✓`, `已在 Meta 广告后台暂停 ${a?.code} · ✓`), "success");
  }
  function onScaleAd(adId) {
    setScaledAds(s => new Set([...s, adId]));
    const a = ADS.find(x => x.id === adId);
    const tt = window.t;
    pushToast(tt(`Scaled ${a?.code} budget +30% · synced with Meta`, `${a?.code} 预算扩量 +30% · 已同步到 Meta`), "success");
  }
  // Winners: spin off a clone as a fresh test before the trend decays.
  // Behaves like a kickstarted iteration — fires a running task that lands
  // in the Tasks panel and ends up under Iteration history when it finishes.
  function onCloneAd(adId) {
    const a = ADS.find(x => x.id === adId);
    if (!a) return;
    const tt = window.t;
    const newTask = {
      id: "task-clone-" + Date.now(),
      status: "running",
      adId: a.id, adCode: a.code,
      recId: "rec-clone-winner",
      recTitle: tt("Clone winner as new test", "克隆赢家做新测试"),
      action_kind: "image_gen",
      startedAt: Date.now(),
      eta: 22, progress: 6,
      _simulatedDuration: 6500,
      _bornAt: Date.now(),
    };
    setTasks(cur => [newTask, ...cur]);
    pushToast(tt(
      `Cloning ${a.code} as a new test · check Tasks`,
      `正在克隆 ${a.code} 做新测试 · 查看任务面板`
    ), "running");
    setTasksPopOpen(true);
  }

  // ===== Iterate flows =====
  function startIterate(adId, recIds) {
    setModalState({ open: true, adId, recIds });
  }
  function closeModal() { setModalState(m => ({ ...m, open: false })); }

  function confirmGenerate(opts) {
    const { adId, recIds } = modalState;
    const targetAd = ADS.find(a => a.id === adId);
    if (!targetAd) return;

    const recs = recIds.map(id => REC_TEMPLATES.find(x => x.id === id)).filter(Boolean);

    // Synchronous kinds — no Variants page; toast immediately and bump iteration count.
    const syncKinds = new Set(["targeting_change", "video_edit"]);
    const syncRecs = recs.filter(r => syncKinds.has(r.action_kind));
    const asyncRecs = recs.filter(r => !syncKinds.has(r.action_kind));

    const tt = window.t;
    syncRecs.forEach(r => {
      setIterationsByAd(prev => ({ ...prev, [adId]: (prev[adId] || 0) + 1 }));
      if (r.action_kind === "targeting_change") {
        pushToast(tt(`Targeting updated for ${targetAd.code} · synced with Meta`, `${targetAd.code} 的受众已更新 · 已同步到 Meta`), "success");
      } else if (r.action_kind === "video_edit") {
        pushToast(tt(`Brief exported for ${targetAd.code} · sent to your shared drive`, `${targetAd.code} 的 brief 已导出 · 已发送到共享盘`), "success");
      }
    });

    // Async kinds — create running tasks.
    const newTasks = asyncRecs.map((r, i) => ({
      id: "task-n" + Date.now() + "-" + i,
      status: "running",
      adId, adCode: targetAd.code,
      recId: r.id, recTitle: r.title,
      action_kind: r.action_kind,
      startedAt: Date.now(),
      eta: 25 + i * 5,
      progress: 8 + i * 3,
      _simulatedDuration: (r.action_kind === "copy_overlay" ? 5000 : 7000) + i * 1200,
      _bornAt: Date.now(),
    }));
    if (newTasks.length) {
      setTasks(cur => [...newTasks, ...cur]);
      pushToast(tt(`Queued ${newTasks.length} generation${newTasks.length > 1 ? "s" : ""} · check Tasks`, `已排队 ${newTasks.length} 个生成任务 · 查看任务面板`), "running");
      setTasksPopOpen(true);
    }

    closeModal();
    closeDrawer();
  }

  // Escape key closes any open overlay (drawer / modal / tasks pop / rationale)
  useEffect(() => {
    const onKey = (e) => {
      if (e.key !== "Escape") return;
      if (createModalOpen) { setCreateModalOpen(false); return; }
      if (modalState.open) { closeModal(); return; }
      if (drawerOpen) { closeDrawer(); return; }
      if (tasksPopOpen) { setTasksPopOpen(false); return; }
      if (rationaleOpen) { setRationaleOpen(false); return; }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [createModalOpen, modalState.open, drawerOpen, tasksPopOpen, rationaleOpen]);

  // Tick running tasks
  useEffect(() => {
    const id = setInterval(() => {
      setTasks(curr => curr.map(tk => {
        if (tk.status !== "running") return tk;
        if (!tk._bornAt) return tk;
        const elapsed = Date.now() - tk._bornAt;
        const ratio = elapsed / tk._simulatedDuration;
        if (ratio >= 1) {
          setIterationsByAd(prev => ({ ...prev, [tk.adId]: (prev[tk.adId] || 0) + 1 }));
          const tt = window.t;
          const kindLabel = tk.action_kind === "copy_overlay" ? tt("Copy variants", "文案变体") : tt("Variants", "变体");
          pushToast(tt(`${kindLabel} ready for ${tk.adCode} · ${tk.recTitle}`, `${tk.adCode} 的${kindLabel}已就绪 · ${tk.recTitle}`), "success");
          return { ...tk, status: "completed", completedAt: Date.now() };
        }
        const progress = Math.min(98, Math.round(ratio * 100));
        const eta = Math.max(1, Math.round((tk._simulatedDuration - elapsed) / 1000));
        return { ...tk, progress, eta };
      }));
    }, 500);
    return () => clearInterval(id);
  }, []);

  // ===== View variants =====
  function viewVariantsByTask(task) {
    setCurrentVariantTaskId(task.id);
    setSelectedAdId(task.adId);
    setScreen("variants");
    setDrawerOpen(false);
    setTasksPopOpen(false);
  }
  function viewVariantsByAdAndRec(adId, recId) {
    const tk = tasks.find(x => x.adId === adId && x.recId === recId && x.status === "completed");
    if (tk) viewVariantsByTask(tk);
  }
  function onShowHistory(adId) {
    // jump to the most-recent completed task for that ad
    const completed = tasks.filter(t => t.status === "completed" && t.adId === adId);
    if (completed.length === 0) return;
    completed.sort((a, b) => (b.completedAt || 0) - (a.completedAt || 0));
    viewVariantsByTask(completed[0]);
  }
  window.__viewVariants = viewVariantsByAdAndRec;

  // M4 (A-4): expose feedback handlers globally so HeroRec can trigger them.
  window.__openFeedback = (rec, ad, done) => setFeedbackState({ open: true, rec, ad, done });
  window.__markUseful = (rec, ad) => {
    const tt = window.t;
    const isZh = window.getLang() === "zh";
    const title = (isZh && rec.titleZh) ? rec.titleZh : rec.title;
    pushToast(tt(`Got it — we'll surface more «${title}»–style recs for ${ad?.code || "this account"}.`, `收到 —— 之后会给 ${ad?.code || "这个账号"} 多推「${title}」这类建议。`), "success");
  };
  function submitFeedback({ reasonId, text }) {
    const tt = window.t;
    const isZh = window.getLang() === "zh";
    const rec = feedbackState.rec;
    const ad = feedbackState.ad;
    const reasonLabel =
      reasonId === "off_persona" ? tt("wrong persona", "人群画像不对")
      : reasonId === "bad_example" ? tt("weak example", "示例较弱")
      : reasonId === "wrong_metric" ? tt("wrong metric", "指标不对")
      : reasonId === "already_tried" ? tt("already tested", "已经试过")
      : tt("your reason", "你填的原因");
    const recTitle = (isZh && rec?.titleZh) ? rec.titleZh : (rec?.title || tt("this rec", "这条建议"));
    pushToast(
      tt(
        `Got it — we'll de-prioritize «${recTitle}» for similar ${ad?.code?.split("-")[0] || "Lipsum"} ads. (${reasonLabel})`,
        `收到 —— 会给同类型 ${ad?.code?.split("-")[0] || "Lipsum"} 广告的「${recTitle}」建议降权。(${reasonLabel})`
      ),
      "success"
    );
    // Trigger the inline widget's "submitted" state
    if (typeof feedbackState.done === "function") feedbackState.done();
    setFeedbackState({ open: false, rec: null, ad: null, done: null });
  }

  function goBackToRadar() {
    setScreen("radar");
    setCurrentVariantTaskId(null);
  }

  const currentVariantTask = tasks.find(x => x.id === currentVariantTaskId);
  const variantAd = currentVariantTask ? ADS.find(a => a.id === currentVariantTask.adId) : null;

  // Round 4: newly-created ads (from Raya panel) prepend to the Radar
  // list, decorated with `_created` timestamp + `_highlight` so Radar
  // can render the glow + "just created" pill + auto-scroll.
  function pushCreatedAdToRadar({ variant, prompt }) {
    const tt = window.t;
    const isZh = window.getLang() === "zh";
    const id = `ad-new-${Date.now()}`;
    const idx = createdAds.length + 1;
    const code = `NEW-${String(idx).padStart(2, "0")}`;
    const newAd = {
      id,
      code,
      type: "image",
      headline: variant?.name || tt("Newly created creative", "新建创意"),
      headlineZh: variant?.nameZh || variant?.name || "新建创意",
      sub: prompt ? (prompt.length > 60 ? prompt.slice(0, 60) + "…" : prompt) : tt("Generated via Raya", "通过 Raya 生成"),
      subZh: prompt ? (prompt.length > 60 ? prompt.slice(0, 60) + "…" : prompt) : "通过 Raya 生成",
      name: `${code} · ${variant?.name || "Raya creative"}`,
      grade: null,
      subGrades: { roas: null, hook: null, retention: null, ctr: null },
      spend: 0,
      roas: 0,
      impressions: 0,
      recType: null,
      persona: tt("Pending data — needs warmup", "等待数据 —— 还在预热"),
      age: tt("just now", "刚刚"),
      perfText: tt(
        "This ad was created from Raya in the Playground. Live data will land after Meta finishes the first delivery window (~2 hours).",
        "这条广告是从 Playground 的 Raya 创建的。等 Meta 跑完第一个投放窗口(约 2 小时),数据会上来。"
      ),
      recs: [],
      _created: Date.now(),
      _highlight: true,
      _isRayaCreated: true,
    };
    setCreatedAds(cur => [newAd, ...cur]);
    setNewAdScrollTrigger(n => n + 1);
    setScreen("radar");
    pushToast(
      tt(
        `Pushed «${variant?.name || "your variant"}» to Meta Ads Manager as ${code}. Data lands in ~2 hours.`,
        `已把「${variant?.name || "你的变体"}」推到 Meta 广告管理后台,编号 ${code}。约 2 小时后会有数据。`
      ),
      "success"
    );
  }
  // Expose for the Playground / Variants screens to call directly.
  window.__pushCreatedAdToRadar = pushCreatedAdToRadar;

  function openCreateAdModal(scaffold) {
    setRayaScaffoldPrompt(scaffold || "");
    setCreateModalOpen(true);
  }

  // Filter out paused ads from radar list — visually keep them but tint.
  // Round 4: prepend Raya-created ads at the top so they're easy to spot.
  const adsForRadar = [
    ...createdAds,
    ...ADS.map(a => ({
      ...a,
      _paused: pausedAds.has(a.id),
      _scaled: scaledAds.has(a.id),
    })),
  ];

  // Screen labels for the topbar
  const tt = window.t;
  const screenLabel =
    screen === "radar" ? tt("Radar", "Radar")
    : screen === "history" ? tt("Iteration history", "迭代历史")
    : screen === "pulse" ? tt("Pulse", "Pulse")
    : screen === "overview" ? tt("Overview", "总览")
    : screen === "playground" ? tt("AI Playground", "AI 实验场")
    : screen === "image-ads" ? tt("Image Ads", "图片广告")
    : screen === "brands" ? tt("Brands", "品牌")
    : (variantAd?.recs.find(r => r.id === currentVariantTask?.recId)?.action_kind === "copy_overlay" ? tt("Copy Ads", "文案广告") : tt("Image Ads", "图片广告"));
  const breadcrumb =
    screen === "variants" && variantAd ? tt(`Iteration · ${variantAd.code}`, `迭代 · ${variantAd.code}`)
    : screen === "history" ? tt(`Across ${Object.keys(completedTasksByAd).length} ads`, `横跨 ${Object.keys(completedTasksByAd).length} 条广告`)
    : screen === "pulse" ? tt(`${(PULSE_ALERTS || []).filter(a => a.severity === "critical").length} critical · live`, `${(PULSE_ALERTS || []).filter(a => a.severity === "critical").length} 条严重 · 实时`)
    : screen === "overview" ? (activeBrand?.name || "Lipsum Brand")
    : screen === "playground" ? tt("Sandbox", "沙盒")
    : screen === "image-ads" ? tt(`${(IMAGE_AD_PROJECTS || []).length} projects`, `${(IMAGE_AD_PROJECTS || []).length} 个项目`)
    : screen === "brands" ? tt(`${(BRANDS || []).length} brands`, `${(BRANDS || []).length} 个品牌`)
    : null;

  return (
    <>
      <Sidebar
        screen={screen}
        onNavigate={(s) => { setScreen(s); setDrawerOpen(false); setTasksPopOpen(false); setFocusedAlertId(null); }}
        activeBrand={activeBrand}
        brands={BRANDS}
        onSwitchBrand={(b) => {
          setActiveBrandId(b.id);
          pushToast(window.t(`Switched to ${b.name}`, `已切换到 ${b.name}`), "success");
        }}
      />
      <div className="app-main">
        <TopBar
          runningCount={runningCount}
          onOpenTasks={() => setTasksPopOpen(o => !o)}
          onOpenRationale={() => setRationaleOpen(true)}
          onOpenOnboarding={() => setOnboardingOpen(true)}
          screenLabel={screenLabel}
          // On the Variants page the "图片广告" / "Image Ads" segment should
          // jump back to the Radar (which is where the iteration started).
          // On other screens, clicking the screen label is a no-op (you are
          // already on that screen).
          screenOnClick={screen === "variants" ? goBackToRadar : null}
          breadcrumb={breadcrumb}
          // Breadcrumb is only clickable when there's a meaningful place to
          // go back to (variants → back to Radar drawer for that ad).
          breadcrumbOnClick={screen === "variants" && variantAd ? () => { setScreen("radar"); setCurrentVariantTaskId(null); setSelectedAdId(variantAd.id); setDrawerOpen(true); } : null}
        />
        <div className="content">
          {screen === "radar" && (
            <Radar
              ads={adsForRadar}
              iterationsByAd={iterationsByAd}
              runningTasksByAd={runningTasksByAd}
              alertsByAd={alertsByAd}
              onOpenAd={openAd}
              onShowHistory={onShowHistory}
              onPause={onPauseAd}
              onScale={onScaleAd}
              onCloneAd={onCloneAd}
              onOpenPulse={(alertId) => { setFocusedAlertId(alertId); setScreen("pulse"); }}
              onCreateAd={() => openCreateAdModal()}
              newAdScrollTrigger={newAdScrollTrigger}
            />
          )}
          {screen === "pulse" && Pulse && (
            <Pulse
              alerts={PULSE_ALERTS}
              ads={ADS}
              focusedAlertId={focusedAlertId}
              onOpenAd={(adId) => { setFocusedAlertId(null); openAd(adId); setScreen("radar"); }}
              onBackToRadar={() => { setFocusedAlertId(null); setScreen("radar"); }}
            />
          )}
          {screen === "overview" && Overview && (
            <Overview
              ads={ADS}
              tasks={tasks}
              alerts={PULSE_ALERTS}
              iterationsByAd={iterationsByAd}
              brand={activeBrand}
              onNavigate={(s) => setScreen(s)}
              onOpenAlert={(alertId) => { setFocusedAlertId(alertId); setScreen("pulse"); }}
              onCreateAd={() => openCreateAdModal()}
            />
          )}
          {screen === "playground" && Playground && (
            <Playground
              demos={PLAYGROUND_DEMOS}
              onBackToRadar={goBackToRadar}
              onPushCreatedAdToRadar={pushCreatedAdToRadar}
              scaffoldPrompt={rayaScaffoldPrompt}
              onConsumeScaffold={() => setRayaScaffoldPrompt("")}
            />
          )}
          {screen === "image-ads" && ImageAds && (
            <ImageAds projects={IMAGE_AD_PROJECTS} brands={BRANDS} onBackToRadar={goBackToRadar} />
          )}
          {screen === "brands" && BrandsList && (
            <BrandsList
              brands={BRANDS}
              activeBrandId={activeBrandId}
              onSwitch={(b) => {
                setActiveBrandId(b.id);
                pushToast(window.t(`Switched to ${b.name}`, `已切换到 ${b.name}`), "success");
              }}
              onBackToRadar={goBackToRadar}
            />
          )}
          {screen === "history" && IterationHistory && (
            <IterationHistory
              tasks={tasks}
              ads={ADS}
              onOpenTask={viewVariantsByTask}
              onBackToRadar={goBackToRadar}
            />
          )}
          {screen === "variants" && variantAd && currentVariantTask && (
            <Variants
              task={currentVariantTask}
              ad={variantAd}
              allTasksForAd={(completedTasksByAd[variantAd.id] || [])}
              onBackToRadar={goBackToRadar}
              onPushedToPlatform={(n) => {
                if (n < 0) {
                  // Download path — abs(n) is the count
                  const k = -n;
                  pushToast(window.t(
                    `Started downloading ${k} variant${k>1?"s":""} (demo — files aren't actually generated).`,
                    `已开始下载 ${k} 个变体(演示版本 —— 不会真的生成文件)。`
                  ), "success");
                } else {
                  pushToast(window.t(
                    `Pushed ${n} variant${n>1?"s":""} to Meta Ads Manager`,
                    `已把 ${n} 个变体推回 Meta 广告管理后台`
                  ), "success");
                }
              }}
            />
          )}

        </div>
        {/* DetailDrawer is mounted as a sibling of .content (NOT inside it)
            so its full-screen overlay doesn't scroll with the Radar table.
            CSS anchors it absolutely inside .app-main below the 56px topbar. */}
        <DetailDrawer
          ad={ad}
          open={drawerOpen}
          initialTab={drawerInitialTab}
          openSeq={drawerOpenSeq}
          onClose={closeDrawer}
          completedTasksForAd={completedTasksByAd[selectedAdId] || []}
          onIterate={(adId, recIds) => startIterate(adId, recIds)}
          onIterateBatch={(adId, recIds) => startIterate(adId, recIds)}
        />
      </div>

      <ActionModal
        open={modalState.open}
        ad={ADS.find(a => a.id === modalState.adId)}
        recIds={modalState.recIds}
        onClose={closeModal}
        onConfirm={confirmGenerate}
      />

      {/* M4 (A-4): structured «not for me» feedback */}
      {FeedbackModal && (
        <FeedbackModal
          open={feedbackState.open}
          rec={feedbackState.rec}
          ad={feedbackState.ad}
          onClose={() => setFeedbackState({ open: false, rec: null, ad: null, done: null })}
          onSubmit={submitFeedback}
        />
      )}

      <TasksPanel
        open={tasksPopOpen}
        tasks={tasks}
        ads={ADS}
        onClose={() => setTasksPopOpen(false)}
        onOpenTask={viewVariantsByTask}
      />

      <RationaleDrawer open={rationaleOpen} onClose={() => setRationaleOpen(false)} />

      {/* Round 4: + 创建广告创意 entry-point modal. Lets the user pick
          between Raya-guided creation (chat in Playground) and the manual
          path (jump to Image Ads). */}
      {window.CreateAdModal && (
        <window.CreateAdModal
          open={createModalOpen}
          onClose={() => setCreateModalOpen(false)}
          onPickRaya={(scaffold) => {
            setRayaScaffoldPrompt(scaffold || "");
            setCreateModalOpen(false);
            setScreen("playground");
          }}
          onPickManual={() => {
            setCreateModalOpen(false);
            setScreen("image-ads");
            pushToast(window.t(
              "Opened Image Ads — pick «New blank project» to start manually.",
              "已打开「图片广告」 —— 选「新建空项目」就能手动开始。"
            ), "success");
          }}
        />
      )}

      {/* First-visit onboarding (fires once, localStorage-backed) */}
      {onboardingOpen && window.Onboarding && (
        <window.Onboarding onClose={() => setOnboardingOpen(false)} />
      )}

      <div className="toasts">
        {toasts.map(t => (
          <div key={t.id} className="toast" onClick={() => {
            if (t.kind === "running") setTasksPopOpen(true);
          }}>
            <span>{t.kind === "success" ? "✓" : t.kind === "running" ? "•" : "!"}</span>
            <span>{t.text}</span>
          </div>
        ))}
      </div>

      <TweaksPanel>
        <TweakSection label="Theme">
          <TweakRadio
            label="Visual"
            value={tw.theme}
            onChange={v => setTweak("theme", v)}
            options={[
              { value: "warm", label: "Warm" },
              { value: "slate", label: "Slate" },
              { value: "editorial", label: "Editorial" },
            ]}
          />
        </TweakSection>
        <TweakSection label="Demo shortcuts" />
        <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
          <button className="twk-field" style={demoBtnStyle()} onClick={() => {
            // TC-01 — open iterate-type ad, drawer opens to hero rec
            const first = ADS.find(a => a.recType === "Iterate" && a.type === "image");
            if (first) openAd(first.id);
          }}>TC-01 · open an iterate-rec ad</button>
          <button className="twk-field" style={demoBtnStyle()} onClick={() => {
            // TC-02 — batch iterate 3 recs (mixed kinds)
            const first = ADS.find(a => a.recType === "Iterate" && a.type === "image");
            if (!first) return;
            openAd(first.id);
            setTimeout(() => {
              startIterate(first.id, [first.recs[0].id, first.recs[1].id, first.recs[2].id]);
            }, 350);
          }}>TC-02 · batch 3 mixed-kind moves</button>
          <button className="twk-field" style={demoBtnStyle()} onClick={() => {
            const video = ADS.find(a => a.type === "video");
            if (video) openAd(video.id);
          }}>TC-04 · open a video ad</button>
          <button className="twk-field" style={demoBtnStyle()} onClick={() => {
            const done = tasks.find(x => x.status === "completed");
            if (done) viewVariantsByTask(done);
          }}>TC-07 · jump to Variants</button>
          <button className="twk-field" style={demoBtnStyle()} onClick={() => {
            // History demo — first ad with iterations
            const adWithHist = Object.keys(iterationsByAd).find(id => (iterationsByAd[id] || 0) > 0);
            if (adWithHist) onShowHistory(adWithHist);
          }}>06 · iteration history (badge click)</button>
          <button className="twk-field" style={demoBtnStyle()} onClick={() => setTasksPopOpen(true)}>
            Open Tasks panel
          </button>
        </div>
      </TweaksPanel>
    </>
  );
}

function demoBtnStyle() {
  return {
    textAlign: "left",
    padding: "5px 8px",
    fontSize: 11,
    cursor: "pointer",
    border: "1px solid rgba(0,0,0,0.08)",
    borderRadius: 6,
    background: "rgba(255,255,255,0.5)",
  };
}

const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(<App />);
