(() => {
  const $ = (sel) => document.querySelector(sel);

  const screens = {
    start: $("#screen-start"),
    option: $("#screen-option"),
    quiz: $("#screen-quiz"),
    result: $("#screen-result"),
    gallery: $("#screen-gallery"),
  };

  const btnStart = $("#btnStart");
  const btnOption = $("#btnOption");
  const btnExit = $("#btnExit");

  const bgmEl = document.getElementById("bgm");
  let bgmWasPlayingBeforePopup = false;


  const btnGallery = $("#btnGallery");
  const btnResetProgress = $("#btnResetProgress");
  const btnOptBack = $("#btnOptBack");

  const galleryList = $("#galleryList");
  const btnGalleryBack = $("#btnGalleryBack");

  const progress = $("#progress");
  const scoreEl = $("#score");
  const questionEl = $("#question");
  const choicesEl = $("#choices");
  const btnQuit = $("#btnQuit");

  const resultTitle = $("#resultTitle");
  const resultText = $("#resultText");
  const btnReplay = $("#btnReplay");
  const btnToTitle = $("#btnToTitle");

  const popup = $("#popup");

  const punishCaption = document.getElementById("punishCaption");

  const showPunishCaption = () => {
    if(punishCaption){
      punishCaption.classList.remove("hidden");
    }
  };

  const hidePunishCaption = () => {
    if(punishCaption){
      punishCaption.classList.add("hidden");
    }
  };

  const popupVideo = $("#popupVideo");
  const popupClose = $("#popupClose");
  const toast = $("#toast");

  // Inject image node into popup card (video fallback)
  const popupCard = popup.querySelector(".popup-card");
  const popupImg = document.createElement("img");
  popupImg.id = "popupImg";
  popupImg.alt = "popup image";
  popupImg.style.width = "100%";
  popupImg.style.height = "auto";
  popupImg.style.maxHeight = "calc(80vh - 52px)";
  popupImg.style.borderRadius = "12px";
  popupImg.style.display = "none";
  popupCard.appendChild(popupImg);

  // Simple overlay play button (shown when autoplay is blocked)
  const playOverlay = document.createElement("button");
  playOverlay.type = "button";
  playOverlay.textContent = "▶ 再生";
  playOverlay.style.position = "absolute";
  playOverlay.style.left = "50%";
  playOverlay.style.top = "50%";
  playOverlay.style.transform = "translate(-50%, -50%)";
  playOverlay.style.padding = "14px 18px";
  playOverlay.style.fontSize = "18px";
  playOverlay.style.borderRadius = "14px";
  playOverlay.style.border = "0";
  playOverlay.style.cursor = "pointer";
  playOverlay.style.boxShadow = "0 10px 24px rgba(0,0,0,.35)";
  playOverlay.style.display = "none";
  playOverlay.style.zIndex = "5";
  popupCard.style.position = "relative";
  popupCard.appendChild(playOverlay);

  // Intro (between Start screen and Quiz) - shows an image with a "Next" button.
  const introNext = document.createElement("button");
  introNext.textContent = "次へ";
  introNext.style.position = "absolute";
  introNext.style.right = "18px";
  introNext.style.bottom = "18px";
  introNext.style.padding = "10px 14px";
  introNext.style.border = "none";
  introNext.style.borderRadius = "12px";
  introNext.style.background = "rgba(0,0,0,0.65)";
  introNext.style.color = "#fff";
  introNext.style.fontWeight = "700";
  introNext.style.cursor = "pointer";
  introNext.style.display = "none";
  popupCard.appendChild(introNext);

  let introCallback = null;
  introNext.addEventListener("click", () => {
    const cb = introCallback;
    introCallback = null;
    closeVideoPopup();
    try { cb && cb(); } catch(e) { console.error(e); }
  });


  const showPlayOverlay = (onClick) => {
    playOverlay.style.display = "block";
    const handler = () => {
      playOverlay.style.display = "none";
      playOverlay.removeEventListener("click", handler);
      try { onClick && onClick(); } catch(e) {}
    };
    playOverlay.addEventListener("click", handler);
  };

  const beep = (freq=660, ms=70) => {
    try {
      const ctx = new (window.AudioContext || window.webkitAudioContext)();
      const o = ctx.createOscillator();
      const g = ctx.createGain();
      o.type = "sine";
      o.frequency.value = freq;
      g.gain.value = 0.04;
      o.connect(g);
      g.connect(ctx.destination);
      o.start();
      setTimeout(() => { o.stop(); ctx.close(); }, ms);
    } catch(e) {}
  };

  const state = {
    settings: { count: 10, pass: 7, sfx: "on" },
    progress: { passCount: 0 },
    questions: [],
    order: [],
    idx: 0,
    correct: 0,
    streak: 0,
    locked: false,
    currentCorrectIndex: 0, // after shuffle
    isFinished: false,
    finishHandled: false,
  };

  const showToast = (msg) => {
    toast.textContent = msg;
    toast.classList.remove("hidden");
    clearTimeout(showToast._t);
    showToast._t = setTimeout(() => toast.classList.add("hidden"), 1400);
  };

  const applyBgm = async (forcePlay=false) => {
    if (!bgmEl) return;
    const on = (state.settings.bgm !== "off");
    bgmEl.volume = 0.35;
    if (!on) {
      try { bgmEl.pause(); } catch(e) {}
      return;
    }
    if (!forcePlay) return;
    try {
      await bgmEl.play();
    } catch(e) {
      // Autoplay blocked until user gesture; ignore.
    }
  };

  const playSfx = (type) => {
    if (state.settings.sfx !== "on") return;
    if (type === "click") beep(520, 50);
    if (type === "ok") beep(820, 80);
    if (type === "ng") beep(220, 120);
  };

  
  const renderGallery = () => {
    if (!galleryList) return;
    const pc = state.progress.passCount || 0;

    const items = [
      { key: "reward1",  label: "合格1回：ご褒美動画",  need: 1,  type: "video", src: "assets/reward_1.mp4" },
      { key: "reward3",  label: "合格3回：ご褒美動画",  need: 3,  type: "video", src: "assets/reward_3.mp4" },
      { key: "reward5",  label: "合格5回：ご褒美動画",  need: 5,  type: "video", src: "assets/reward_5.mp4" },
      { key: "reward7",  label: "合格7回：ご褒美動画",  need: 7,  type: "video", src: "assets/reward_7.mp4" },
      { key: "reward10", label: "合格10回：ご褒美動画", need: 10, type: "video", src: "assets/reward_10.mp4" },
      { key: "punish",   label: "不合格：お仕置き動画", need: 0,  type: "video", src: "assets/punish.mp4" },
    ];

    galleryList.innerHTML = "";
    items.forEach(it => {
      const unlocked = pc >= it.need;
      const btn = document.createElement("button");
      btn.className = "btn " + (unlocked ? "primary" : "");
      btn.textContent = unlocked ? it.label : "？？？（未解放）";
      btn.disabled = !unlocked;
      btn.addEventListener("click", () => {
        playSfx("click");
        if (it.type === "video") showPopupVideo(it.src, "assets/start.png");
        else showPopupImage(it.src);
      });
      galleryList.appendChild(btn);
    });
  };

const setScreen = (name) => {
    Object.values(screens).forEach(s => s.classList.remove("active"));
    screens[name].classList.add("active");
  };

  const loadSettings = () => {
    try {
      const raw = localStorage.getItem("celine_toeic_settings");
      if (!raw) return;
      const s = JSON.parse(raw);
      if (typeof s.count === "number") state.settings.count = s.count;
      if (typeof s.pass === "number") state.settings.pass = s.pass;
      if (s.sfx === "on" || s.sfx === "off") state.settings.sfx = s.sfx;
      if (s.bgm === "on" || s.bgm === "off") state.settings.bgm = s.bgm;
    } catch(e) {}
  };

  const loadProgress = () => {
    try {
      const raw = localStorage.getItem("celine_toeic_progress");
      if (!raw) return;
      const p = JSON.parse(raw);
      if (typeof p.passCount === "number" && p.passCount >= 0) state.progress.passCount = Math.floor(p.passCount);
    } catch(e) {}
  };

  const saveProgress = () => {
    try {
      localStorage.setItem("celine_toeic_progress", JSON.stringify({ passCount: state.progress.passCount }));
    } catch(e) {}
  };

  const resetProgress = () => {
    try {
      state.progress.passCount = 0;
      localStorage.removeItem("celine_toeic_progress");
      saveProgress();
    } catch(e) {}
  };


  const syncOptionUI = () => {};

  const clampInt = (n, lo, hi) => {
    if (!Number.isFinite(n)) return lo;
    return Math.max(lo, Math.min(hi, n));
  };

  const saveSettings = () => {};

  const shuffle = (arr) => {
    for (let i = arr.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
  };

  const loadQuestions = async () => {
    if (Array.isArray(window.CELINE_QUESTIONS) && window.CELINE_QUESTIONS.length) {
      state.questions = window.CELINE_QUESTIONS;
    }
    if (location.protocol !== "file:") {
      try {
        const res = await fetch("assets/questions.json", { cache: "no-store" });
        const data = await res.json();
        if (Array.isArray(data) && data.length) state.questions = data;
      } catch(e) {}
    }
    const ok = Array.isArray(state.questions) && state.questions.every(x =>
      x && typeof x.q === "string" &&
      Array.isArray(x.choices) && x.choices.length === 4 &&
      Number.isInteger(x.a) && x.a >= 0 && x.a < 4
    );
    if (!ok) throw new Error("questions format error");
  };

  const startGame = () => {
    const n = Math.min(state.settings.count, state.questions.length);
    state.order = shuffle([...Array(state.questions.length).keys()]).slice(0, n);
    state.idx = 0;
    state.correct = 0;
    state.streak = 0;
    state.isFinished = false;
    state.finishHandled = false;
    state.locked = false;
    renderQuestion();
    setScreen("quiz");
  };

  const renderQuestion = () => {
    const total = state.order.length;
    const qIndex = state.order[state.idx];
    const q = state.questions[qIndex];

    progress.textContent = `Q ${state.idx + 1} / ${total}`;
    scoreEl.textContent = `Correct ${state.correct}`;
    questionEl.textContent = q.q;

    // Shuffle choices each time, while keeping track of correct index
    const packed = q.choices.map((t, i) => ({ t, isCorrect: i === q.a }));
    shuffle(packed);
    state.currentCorrectIndex = packed.findIndex(x => x.isCorrect);

    choicesEl.innerHTML = "";
    packed.forEach((item, i) => {
      const b = document.createElement("button");
      b.className = "choice";
      b.type = "button";
      b.textContent = item.t;
      b.addEventListener("click", () => onAnswer(i));
      choicesEl.appendChild(b);
    });
  };

  const onAnswer = (choiceIndex) => {
    if (state.locked || state.isFinished) return;
    state.locked = true;

    const buttons = [...choicesEl.querySelectorAll(".choice")];

    buttons.forEach((b, i) => {
      if (i === state.currentCorrectIndex) b.classList.add("correct");
      if (i === choiceIndex && i !== state.currentCorrectIndex) b.classList.add("wrong");
      b.disabled = true;
    });

    const correct = (choiceIndex === state.currentCorrectIndex);
    if (correct) {
      state.correct += 1;
      state.streak += 1;
      playSfx("ok");

      if(state.streak >= 5){
        showToast("…素晴らしいわ。");
      } else if(state.streak >= 3){
        showToast("調子がいいわね。");
      } else {
        showToast("Correct");
      }

    } else {
      state.streak = 0;
      playSfx("ng");
      showToast("Wrong");
    }

    setTimeout(() => {
      state.idx += 1;
      state.locked = false;
      if (state.idx >= state.order.length) {
        state.isFinished = true;
        finishGame();
      } else {
        renderQuestion();
      }
    }, 650);
  };

  const showPopupImage = (imgSrc) => {
    popupVideo.pause();
    popupVideo.style.display = "none";
    popupImg.src = imgSrc;
    popupImg.style.display = "block";
    popup.classList.remove("hidden");
  };


  const showIntro = (imgSrc, onDone) => {
    // Use the same popup container but as an image-only intro.
    try { popupVideo.pause(); } catch(e) {}
    popupVideo.style.display = "none";
    popupImg.src = imgSrc;
    popupImg.style.display = "block";
    try { playOverlay.style.display = "none"; } catch(e) {}
    introNext.style.display = "inline-block";
    introCallback = onDone || null;
    popup.classList.remove("hidden");
  };


  const showPopupVideo = (videoSrc, fallbackImgSrc) => {
    popupImg.style.display = "none";
    popupVideo.style.display = "block";

    popupVideo.pause();
    popupVideo.removeAttribute("src");
    popupVideo.load();

    popupVideo.src = videoSrc;
    try { popupVideo.controls = false; } catch(e) {}
    try { playOverlay.style.display = "none"; } catch(e) {}
    popup.classList.remove("hidden");

    // Pause BGM while video is playing to avoid double audio.
    try {
      bgmWasPlayingBeforePopup = !!(bgmEl && !bgmEl.paused && !bgmEl.ended);
      if (bgmEl) bgmEl.pause();
    } catch(e) { bgmWasPlayingBeforePopup = false; }

    const onError = () => {
      popupVideo.removeEventListener("error", onError);
      showPopupImage(fallbackImgSrc);
    };
    popupVideo.addEventListener("error", onError);

    popupVideo.play().catch(() => {
      // Autoplay may be blocked (especially for local file://). Keep the video visible and
      // show controls + a simple "Play" overlay so the user can start playback with one click.
      try { popupVideo.controls = true; } catch(e) {}
      showToast("動画は再生ボタン（▶）で再生できます");
      showPlayOverlay(() => { popupVideo.play().catch(()=>{}); });
    });
  };

  const closeVideoPopup = () => {
    hidePunishCaption();
    popup.classList.add("hidden");
    popupVideo.pause();
    try { playOverlay.style.display = "none"; } catch(e) {}
    try { introNext.style.display = "none"; } catch(e) {}
    introCallback = null;
    // Resume BGM if it was playing before popup.
    try {
      if (bgmWasPlayingBeforePopup) applyBgm(true);
    } catch(e) {}
    bgmWasPlayingBeforePopup = false;
  };

  
const finishGame = () => {
  if (state.finishHandled) return;
  state.finishHandled = true;

  const total = state.order.length;
  const correct = state.correct;

  const isPerfect = (correct === total);
  const isSuccess = (correct >= state.settings.pass);

  hidePunishCaption();

  const beforePass = state.progress.passCount;
  let unlockedMsg = "";

  if (isSuccess) {
    state.progress.passCount += 1;
    saveProgress();

    if (beforePass < 1 && state.progress.passCount >= 1) unlockedMsg = "（ご褒美 解放）";
    else if (beforePass < 3 && state.progress.passCount >= 3) unlockedMsg = "（ご褒美② 解放）";
    else if (beforePass < 5 && state.progress.passCount >= 5) unlockedMsg = "（ご褒美③ 解放）";
    else if (beforePass < 7 && state.progress.passCount >= 7) unlockedMsg = "（ご褒美④ 解放）";
    else if (beforePass < 10 && state.progress.passCount >= 10) unlockedMsg = "（最終ご褒美 解放）";
  }

  if (isSuccess) {
    resultTitle.textContent = isPerfect ? "PERFECT" : "SUCCESS";
    resultText.textContent =
      `正解 ${correct} / ${total}  ……${isPerfect ? "完璧ね。" : "悪くないわ。"}\n累計合格：${state.progress.passCount}回 ${unlockedMsg}`.trim();

    const pc = state.progress.passCount;

    // Rewards: 1-10 are videos (reward_1.mp4 ... reward_10.mp4)
    if (pc >= 1 && pc <= 10) {
      showPopupVideo(`assets/reward_${pc}.mp4`, "assets/start.png");
    } else {
      // If somehow exceeds 10, keep showing the final reward video.
      showPopupVideo("assets/reward_10.mp4", "assets/start.png");
    }
  } else {
    resultTitle.textContent = "FAIL";
    resultText.textContent =
      `正解 ${correct} / ${total}  ……努力が足りないのは、見ればわかるわ。\n累計合格：${state.progress.passCount}回`.trim();

    showPunishCaption();
    showPopupVideo("assets/punish.mp4", "assets/start.png");
  }

  setScreen("result");
};


  btnStart.addEventListener("click", async () => { playSfx("click"); await applyBgm(true); showIntro("assets/intro.png", () => startGame()); });
  btnOption.addEventListener("click", () => { playSfx("click"); setScreen("option"); });
  btnExit.addEventListener("click", () => { playSfx("click"); showToast("終了する場合はタブを閉じてください"); });

      if (btnGallery) {
    btnGallery.addEventListener("click", async () => {
      playSfx("click");
      await applyBgm(true);
      renderGallery();
      setScreen("gallery");
    });
  }

if (btnResetProgress) {
    btnResetProgress.addEventListener("click", async () => {
      playSfx("click");
      await applyBgm(true);
      const ok = confirm("累計合格回数をリセットします。よろしいですか？");
      if (!ok) return;
      resetProgress();
      showToast("リセットしました");
    });
  }
  btnOptBack.addEventListener("click", async () => { playSfx("click"); await applyBgm(true); setScreen("start"); });
  if (btnGalleryBack) {
    btnGalleryBack.addEventListener("click", async () => { playSfx("click"); await applyBgm(true); setScreen("option"); });
  }


  btnQuit.addEventListener("click", async () => { playSfx("click"); await applyBgm(true); setScreen("start"); });

  btnReplay.addEventListener("click", () => { playSfx("click"); startGame(); });
  btnToTitle.addEventListener("click", async () => { playSfx("click"); await applyBgm(true); setScreen("start"); });

  popupClose.addEventListener("click", closeVideoPopup);
  popup.querySelector(".popup-backdrop").addEventListener("click", closeVideoPopup);

  (async () => {
    loadSettings();
    loadProgress();
    syncOptionUI();
    await applyBgm(false);
    try {
      await loadQuestions();
    } catch (e) {
      console.error(e);
      alert("問題データの読み込みに失敗しました。assets/questions.js を確認してください。");
    }
  })();
})();