// app.jsx — メインアプリ（適応型診断エンジン版）

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "hologram",
  "showHints": true
}/*EDITMODE-END*/;

const STORAGE_KEY = "latent.state.v1";
const bridge = window.__latentBridge;
const api = window.__latentAPI;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [stage, setStage] = React.useState("loading");
  const [engine, setEngine] = React.useState(null);
  const [currentQ, setCurrentQ] = React.useState(null);
  const [questionCount, setQuestionCount] = React.useState(0);
  const [maxQuestions, setMaxQuestions] = React.useState(15);
  const [answers, setAnswers] = React.useState([]);
  const [diagnosis, setDiagnosis] = React.useState(null);
  const [demographics, setDemographics] = React.useState({ gender: null, age: null, genre: null });
  const [productSearchStart, setProductSearchStart] = React.useState(null);
  const [thinking, setThinking] = React.useState(null);
  const [apiLoading, setApiLoading] = React.useState(false);
  const [apiError, setApiError] = React.useState(null);

  React.useEffect(() => {
    DiagnosisEngine.load("question-bank.json").then(function (eng) {
      setEngine(eng);
      try {
        const raw = localStorage.getItem(STORAGE_KEY);
        if (raw) {
          const s = JSON.parse(raw);
          if (s.stage === "reveal" && s.diagnosis) {
            setDiagnosis(s.diagnosis);
            setStage("reveal");
            return;
          }
        }
      } catch (_) {}
      setStage("intro");
    }).catch(function (err) {
      console.error("Failed to load question bank:", err);
      setStage("intro");
    });
  }, []);

  React.useEffect(() => {
    if (stage === "loading") return;
    const snap = { stage, diagnosis };
    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(snap)); } catch (_) {}
    bridge && bridge.store.set(snap);
  }, [stage, diagnosis]);

  const goDemo = () => {
    setStage("demo");
  };

  const startQuiz = (demo) => {
    if (!engine) return;
    setDemographics(demo);
    engine.init();
    setQuestionCount(0);
    setAnswers([]);
    setDiagnosis(null);
    setApiError(null);

    const result = engine.next();
    if (result.status === "question") {
      setCurrentQ(result.question);
      setQuestionCount(0);
      setMaxQuestions(result.maxQuestions);
      setStage("quiz");
    }
    bridge && bridge.send({ type: "started", demographics: demo });
  };

  const callDiagnoseAPI = async () => {
    setApiLoading(true);
    setApiError(null);
    setStage("analyzing");

    try {
      const paramOutputs = engine.export();
      bridge && bridge.send({ type: "analyzing", paramOutputs });

      // Phase 1: レポートを取得（商品なし・高速）
      const report = await api.diagnose(paramOutputs, demographics);
      setDiagnosis(report);
      setStage("reveal");
      bridge && bridge.send({ type: "report_ready", diagnosis: report });

      // Phase 2: 商品をバックグラウンドでポーリング
      if (report.session_id) {
        setProductSearchStart(Date.now());
        api.pollProducts(report.session_id, function (result) {
          if (result.status === "done" && result.products) {
            setDiagnosis(function (prev) {
              var updated = Object.assign({}, prev, { products: result.products });
              bridge && bridge.send({ type: "products_ready", products: result.products });
              return updated;
            });
          } else if (result.status === "error") {
            setDiagnosis(function (prev) {
              return Object.assign({}, prev, { productError: result.detail || "商品検索に失敗しました" });
            });
          }
        });
      }
    } catch (e) {
      console.error("API error:", e);
      setApiError(e.message);
      if (window.SAMPLE_DIAGNOSIS) {
        setDiagnosis(window.SAMPLE_DIAGNOSIS);
        setStage("reveal");
      } else {
        setStage("error");
      }
    } finally {
      setApiLoading(false);
    }
  };

  const handleAnswer = (choice) => {
    const answer = choice === "a" ? "A" : "B";

    setThinking({ choice });

    setTimeout(() => {
      const updateResult = engine.update(answer);
      setQuestionCount(updateResult.questionCount);
      setAnswers(function (prev) { return prev.concat([{ id: currentQ.id, answer: answer }]); });

      if (updateResult.terminated) {
        setThinking(null);
        callDiagnoseAPI();
      } else {
        const nextResult = engine.next();
        if (nextResult.status === "question") {
          setCurrentQ(nextResult.question);
          setThinking(null);
        } else {
          setThinking(null);
          callDiagnoseAPI();
        }
      }
    }, 500);
  };

  const reset = () => {
    setStage("intro");
    setQuestionCount(0);
    setCurrentQ(null);
    setAnswers([]);
    setDiagnosis(null);
    setApiError(null);
    bridge && bridge.send({ type: "reset" });
  };

  const handleProductTap = (productId) => {
    bridge && bridge.send({ type: "productTapped", productId });
  };

  React.useEffect(() => {
    if (!window.LATENT) return;
    window.LATENT._bind("start", goDemo);
    window.LATENT._bind("reset", reset);
    window.LATENT._bind("setTheme", (theme) => {
      if (["obsidian", "porcelain", "hologram"].includes(theme)) {
        setTweak("theme", theme);
      }
    });
    window.LATENT._bind("restoreState", (s) => {
      if (!s) return;
      if (s.stage) setStage(s.stage);
      if (s.diagnosis) setDiagnosis(s.diagnosis);
    });
  }, [engine]);

  if (stage === "loading") {
    return (
      <div className={`app theme-${t.theme}`}>
        <div className="bg"><div className="bg-blob bg-blob-1" /><div className="bg-blob bg-blob-2" /><div className="bg-blob bg-blob-3" /><div className="bg-grain" /></div>
        <main className="app-main">
          <div className="analyzing"><div className="analyzing-text"><p className="analyzing-msg">質問データを読み込み中...</p></div></div>
        </main>
      </div>
    );
  }

  return (
    <div className={`app theme-${t.theme}`} data-screen-label={`stage:${stage}`}>
      <div className="bg">
        <div className="bg-blob bg-blob-1" />
        <div className="bg-blob bg-blob-2" />
        <div className="bg-blob bg-blob-3" />
        <div className="bg-grain" />
      </div>

      <header className="app-header">
        <div className="logo">
          <span className="logo-mark">◆</span>
          <span className="logo-text">ホシイカモ</span>
        </div>
        <div className="header-meta">
          {stage === "quiz" && (
            <span className="header-stage">QUESTION {String(questionCount + 1).padStart(2, "0")}</span>
          )}
          {stage === "intro" && <span className="header-stage">READY</span>}
          {stage === "demo" && <span className="header-stage">PROFILE</span>}
          {stage === "analyzing" && <span className="header-stage">ANALYZING</span>}
          {stage === "reveal" && <span className="header-stage">REVEAL</span>}
          {stage === "error" && <span className="header-stage">ERROR</span>}
        </div>
      </header>

      <main className="app-main">
        {stage === "intro" && <IntroScreen onStart={goDemo} />}
        {stage === "demo" && <DemoScreen onComplete={startQuiz} onBack={() => setStage("intro")} />}
        {stage === "quiz" && currentQ && (
          <>
            <SwipeCard
              key={currentQ.id}
              question={currentQ}
              index={questionCount}
              total={maxQuestions}
              onAnswer={handleAnswer}
              prompt="次の2つのうち、より近い方を選んでください。"
            />
            {thinking && <ThinkingOverlay choice={thinking.choice} tags={{}} qIdx={questionCount} />}
          </>
        )}
        {stage === "analyzing" && (
          <AnalyzingScreen />
        )}
        {stage === "reveal" && diagnosis && (
          <RevealScreen
            diagnosis={diagnosis}
            theme={t.theme}
            onReset={reset}
            onProductTap={handleProductTap}
            productSearchStart={productSearchStart}
          />
        )}
        {stage === "error" && (
          <ErrorScreen message={apiError} onRetry={goDemo} onReset={reset} />
        )}
      </main>

      <TweaksPanel title="Tweaks">
        <TweakSection label="操作" />
        <TweakToggle
          label="操作ヒント表示"
          value={t.showHints}
          onChange={(v) => setTweak("showHints", v)}
        />
      </TweaksPanel>
    </div>
  );
}

function IntroScreen({ onStart }) {
  return (
    <div className="intro">
      <div className="intro-orb">
        <div className="intro-orb-core" />
        <div className="intro-orb-ring intro-orb-ring-1" />
        <div className="intro-orb-ring intro-orb-ring-2" />
        <div className="intro-orb-ring intro-orb-ring-3" />
        <div className="intro-orb-shine" />
      </div>
      <div className="intro-eyebrow">10–15 QUESTIONS · ADAPTIVE · NO COMPROMISE</div>
      <h1 className="intro-title">
        まだ言葉に<br/>なっていない<br/><em>欲しいもの</em>を、<br/>見つけにいく。
      </h1>
      <p className="intro-sub">
        二択に答えるだけ。あなたの潜在意識が<br/>
        探していたものを、霧の向こうから連れてきます。
      </p>
      <button className="intro-cta" onClick={onStart}>
        <span className="intro-cta-bg" />
        <span className="intro-cta-text">探索をはじめる</span>
        <span className="intro-cta-arrow">→</span>
      </button>
      <div className="intro-meta">
        <div><span>1:30</span> 所要時間</div>
        <div><span>10–15</span> 質問</div>
        <div><span>5</span> 提案</div>
      </div>
    </div>
  );
}

const GENRE_OPTIONS = [
  { value: null, label: "オールジャンル", sub: "特に絞らない" },
  { value: "fashion", label: "ファッション", sub: "服・靴・バッグ" },
  { value: "cosme", label: "美容・コスメ", sub: "スキンケア・メイク" },
  { value: "fitness", label: "健康・フィットネス", sub: "サプリ・器具・ウェア" },
  { value: "gadget", label: "ガジェット・家電", sub: "デバイス・スマート家電" },
  { value: "food", label: "食品・グルメ", sub: "お取り寄せ・飲料" },
  { value: "book", label: "本・学び", sub: "書籍・講座・教材" },
  { value: "home", label: "インテリア・生活", sub: "家具・雑貨・収納" },
  { value: "experience", label: "体験・サービス", sub: "旅行・チケット・サブスク" },
];

function DemoScreen({ onComplete, onBack }) {
  const [gender, setGender] = React.useState(null);
  const [age, setAge] = React.useState(null);
  const [genre, setGenre] = React.useState(null);

  const canProceed = gender !== null && age !== null;

  const handleStart = () => {
    if (!canProceed) return;
    onComplete({ gender, age, genre });
  };

  return (
    <div className="demo">
      <div className="demo-eyebrow">PROFILE · あなたのことを少しだけ</div>
      <p className="demo-sub">より精度の高い商品提案のために教えてください</p>

      <div className="demo-section">
        <div className="demo-label">性別</div>
        <div className="demo-chips">
          {[
            { value: "male", label: "男性" },
            { value: "female", label: "女性" },
            { value: "other", label: "その他" },
          ].map((opt) => (
            <button
              key={opt.value}
              className={`demo-chip${gender === opt.value ? " demo-chip-active" : ""}`}
              onClick={() => setGender(opt.value)}
            >
              {opt.label}
            </button>
          ))}
        </div>
      </div>

      <div className="demo-section">
        <div className="demo-label">年代</div>
        <div className="demo-chips">
          {[
            { value: "10s", label: "10代" },
            { value: "20s", label: "20代" },
            { value: "30s", label: "30代" },
            { value: "40s", label: "40代" },
            { value: "50s", label: "50代以上" },
          ].map((opt) => (
            <button
              key={opt.value}
              className={`demo-chip${age === opt.value ? " demo-chip-active" : ""}`}
              onClick={() => setAge(opt.value)}
            >
              {opt.label}
            </button>
          ))}
        </div>
      </div>

      <div className="demo-section">
        <div className="demo-label">探したいジャンル <span className="demo-label-opt">任意</span></div>
        <div className="demo-genres">
          {GENRE_OPTIONS.map((opt) => (
            <button
              key={opt.value || "all"}
              className={`demo-genre${genre === opt.value ? " demo-genre-active" : ""}`}
              onClick={() => setGenre(opt.value)}
            >
              <span className="demo-genre-label">{opt.label}</span>
              <span className="demo-genre-sub">{opt.sub}</span>
            </button>
          ))}
        </div>
      </div>

      <button className={`demo-cta${canProceed ? "" : " demo-cta-disabled"}`} onClick={handleStart}>
        <span className="demo-cta-text">質問をはじめる</span>
        <span className="demo-cta-arrow">→</span>
      </button>

      <button className="demo-back" onClick={onBack}>
        <span className="demo-back-arrow">←</span>
        <span>戻る</span>
      </button>
    </div>
  );
}

function ElapsedTimer({ startTime }) {
  const [elapsed, setElapsed] = React.useState(0);

  React.useEffect(() => {
    const t = startTime || Date.now();
    const tick = () => setElapsed(Math.floor((Date.now() - t) / 1000));
    tick();
    const id = setInterval(tick, 1000);
    return () => clearInterval(id);
  }, [startTime]);

  const min = Math.floor(elapsed / 60);
  const sec = elapsed % 60;
  const display = min > 0
    ? `${min}:${String(sec).padStart(2, "0")}`
    : `0:${String(sec).padStart(2, "0")}`;

  return <span className="elapsed-timer">{display}</span>;
}

function AnalyzingScreen() {
  const MESSAGES = [
    "あなたの選択を解析しています",
    "潜在意識のパターンを読み取っています",
    "心理軸のスコアを算出しています",
    "診断レポートを生成しています",
  ];

  const [msgIdx, setMsgIdx] = React.useState(0);
  const [dots, setDots] = React.useState("");
  const [startTime] = React.useState(Date.now);

  React.useEffect(() => {
    const interval = setInterval(() => {
      setMsgIdx((prev) => (prev + 1) % MESSAGES.length);
    }, 8000);
    return () => clearInterval(interval);
  }, []);

  React.useEffect(() => {
    const interval = setInterval(() => {
      setDots((prev) => (prev.length >= 3 ? "" : prev + "."));
    }, 500);
    return () => clearInterval(interval);
  }, []);

  return (
    <div className="analyzing">
      <div className="analyzing-orb">
        <div className="intro-orb-core" />
        <div className="intro-orb-ring intro-orb-ring-1" style={{ animationDuration: "3s" }} />
        <div className="intro-orb-ring intro-orb-ring-2" style={{ animationDuration: "4s" }} />
        <div className="intro-orb-ring intro-orb-ring-3" style={{ animationDuration: "5s" }} />
      </div>
      <div className="analyzing-text">
        <p className="analyzing-msg" key={msgIdx}>{MESSAGES[msgIdx]}{dots}</p>
        <p className="analyzing-sub">あなたの潜在欲求を診断しています</p>
        <div className="analyzing-elapsed">
          <span className="analyzing-elapsed-label">経過時間</span>
          <ElapsedTimer startTime={startTime} />
        </div>
        <div className="analyzing-bar">
          <div className="analyzing-bar-fill" />
        </div>
      </div>
    </div>
  );
}

function ErrorScreen({ message, onRetry, onReset }) {
  return (
    <div className="error-screen">
      <div className="error-icon">⚠</div>
      <h2 className="error-title">解析に失敗しました</h2>
      <p className="error-msg">{message || "サーバーとの通信に問題が発生しました"}</p>
      <div className="error-actions">
        <button className="error-btn error-btn-retry" onClick={onRetry}>もう一度試す</button>
        <button className="error-btn error-btn-reset" onClick={onReset}>最初に戻る</button>
      </div>
    </div>
  );
}

window.ElapsedTimer = ElapsedTimer;

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