(function () {
  const protocol = "localchat.wyr.v1";
  const eventSessionCreated = "session.created";
  const eventPlayerJoined = "player.joined";
  const eventRoundStarted = "round.started";
  const eventVoteCast = "vote.cast";
  const eventVotesRevealed = "votes.revealed";
  const storageKey = "would-you-rather-last";
  const decks = [
    {
      id: "campus",
      label: "Campus",
      questions: [
        ["would you rather", "Find the perfect study spot", "Have the perfect group project team"],
        ["would you rather", "Get free coffee for a month", "Get free campus snacks for a month"],
        ["would you rather", "Always have a quiet library table", "Always have the fastest Wi-Fi"],
        ["would you rather", "Ace one hard exam", "Never miss a deadline"],
        ["would you rather", "Host a game night", "Plan a weekend trip"],
        ["would you rather", "Have a locker that cleans itself", "Have a backpack that feels weightless"]
      ]
    },
    {
      id: "hangout",
      label: "Hangout",
      questions: [
        ["would you rather", "Pick the movie every time", "Pick the snacks every time"],
        ["would you rather", "Only send voice notes", "Only send reaction stickers"],
        ["would you rather", "Win every board game", "Know every karaoke lyric"],
        ["would you rather", "Have a perfect picnic day", "Have a perfect rainy movie day"],
        ["would you rather", "Plan the playlist", "Plan the food"],
        ["would you rather", "Be early to everything", "Always find the best parking spot"]
      ]
    },
    {
      id: "most-likely",
      label: "Most Likely",
      questions: [
        ["most likely to", "Start a study group", "Start a dance break"],
        ["most likely to", "Remember everyone's birthday", "Forget where they parked"],
        ["most likely to", "Pack extra snacks", "Bring the speaker"],
        ["most likely to", "Take the group photo", "Make the funniest caption"],
        ["most likely to", "Find a shortcut", "Turn a delay into a game"],
        ["most likely to", "Win trivia night", "Win the costume contest"]
      ]
    }
  ];

  const state = {
    mode: "",
    role: "",
    roomId: "",
    memberId: "",
    memberName: "",
    deckId: "campus",
    cursor: "0",
    roundIndex: 0,
    round: null,
    votes: {},
    players: {},
    history: [],
    status: "Choose a mode to start.",
    pollTimer: 0
  };

  function api() {
    return window.localchat || {};
  }

  function el(tag, className, text) {
    const node = document.createElement(tag);
    if (className) {
      node.className = className;
    }
    if (text !== undefined && text !== null) {
      node.textContent = text;
    }
    return node;
  }

  function bridge(method, params) {
    const parts = method.split(".");
    let target = api();
    for (let i = 0; i < parts.length; i += 1) {
      target = target && target[parts[i]];
    }
    if (typeof target !== "function") {
      return Promise.resolve({});
    }
    return target(params || {}).catch(function (error) {
      state.status = (error && error.errorMessage) || "Action failed";
      render();
      return {};
    });
  }

  function toast(message) {
    return bridge("ui.showToast", { message: message });
  }

  function storageGet(key) {
    const store = api().storage && api().storage.local;
    if (!store || !store.get) {
      return Promise.resolve("");
    }
    return store.get(key).catch(function () {
      return "";
    });
  }

  function storageSet(key, value) {
    const store = api().storage && api().storage.local;
    if (!store || !store.set) {
      return Promise.resolve();
    }
    return store.set(key, value).catch(function () {});
  }

  function keepScreenOn(enabled) {
    return bridge("ui.setKeepScreenOn", Boolean(enabled));
  }

  function safeId(value, fallback) {
    const raw = String(value || "").trim().replace(/[^a-zA-Z0-9._:-]/g, "-");
    return raw ? raw.slice(0, 80) : fallback;
  }

  function roomCode() {
    return "WYR-" + Math.floor(1000 + Math.random() * 9000);
  }

  function memberId() {
    return "member-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 7);
  }

  function deck() {
    return decks.find(function (item) { return item.id === state.deckId; }) || decks[0];
  }

  function questionFor(index) {
    const currentDeck = deck();
    const item = currentDeck.questions[index % currentDeck.questions.length];
    return {
      prompt: item[0],
      a: item[1],
      b: item[2],
      deckLabel: currentDeck.label
    };
  }

  function nextQuestion() {
    const question = questionFor(state.roundIndex);
    state.roundIndex = (state.roundIndex + 1) % deck().questions.length;
    return question;
  }

  function addPlayer(id, name) {
    const playerId = safeId(id, "");
    if (!playerId) {
      return;
    }
    const playerName = String(name || "Player").trim().slice(0, 32) || "Player";
    state.players[playerId] = { id: playerId, name: playerName };
  }

  function playerRows() {
    const rows = Object.keys(state.players).map(function (id) {
      return state.players[id];
    });
    if (!rows.length && state.memberId) {
      rows.push({ id: state.memberId, name: state.memberName || "You" });
    }
    return rows.sort(function (a, b) {
      return a.name.localeCompare(b.name);
    });
  }

  function sendEvent(event, extra) {
    if (!state.roomId) {
      return Promise.resolve({});
    }
    const payload = Object.assign({
      protocol: protocol,
      event: event,
      sessionId: state.roomId,
      memberId: state.memberId,
      memberName: state.memberName,
      createdAt: new Date().toISOString()
    }, extra || {});
    return bridge("room.message", {
      roomId: state.roomId,
      memberId: state.memberId,
      type: "wyr.event",
      payload: payload
    });
  }

  function isPayload(payload) {
    return payload && payload.protocol === protocol && typeof payload.event === "string";
  }

  function applyPayload(payload) {
    if (!isPayload(payload)) {
      return;
    }
    if (payload.event === eventSessionCreated) {
      state.status = "Room " + (payload.sessionId || state.roomId) + " is ready.";
      return;
    }
    if (payload.event === eventPlayerJoined) {
      addPlayer(payload.memberId, payload.memberName);
      state.status = (payload.memberName || "A player") + " joined.";
      return;
    }
    if (payload.event === eventRoundStarted) {
      state.deckId = payload.deckId || state.deckId;
      state.round = {
        id: payload.roundId,
        prompt: payload.prompt || "would you rather",
        a: payload.a || "Choice A",
        b: payload.b || "Choice B",
        deckLabel: payload.deckLabel || deck().label,
        revealed: false
      };
      state.votes = {};
      state.status = "New round. Cast your vote.";
      keepScreenOn(true);
      return;
    }
    if (payload.event === eventVoteCast) {
      addPlayer(payload.memberId, payload.memberName);
      if (payload.roundId === (state.round && state.round.id)) {
        state.votes[payload.memberId] = payload.choice === "B" ? "B" : "A";
        state.status = (payload.memberName || "A player") + " voted.";
      }
      return;
    }
    if (payload.event === eventVotesRevealed) {
      revealVotes(false);
    }
  }

  function pollRoom() {
    if (!state.roomId || !api().room || !api().room.poll) {
      return;
    }
    bridge("room.poll", {
      roomId: state.roomId,
      cursor: state.cursor,
      limit: 50
    }).then(function (result) {
      const messages = Array.isArray(result.messages) ? result.messages : [];
      messages.forEach(function (message) {
        if (message && message.memberId !== state.memberId) {
          applyPayload(message.payload);
        }
      });
      if (result.nextCursor !== undefined && result.nextCursor !== null) {
        state.cursor = String(result.nextCursor);
      }
      render();
    });
  }

  function startPolling() {
    stopPolling();
    state.pollTimer = window.setInterval(pollRoom, 1200);
    pollRoom();
  }

  function stopPolling() {
    if (state.pollTimer) {
      window.clearInterval(state.pollTimer);
      state.pollTimer = 0;
    }
  }

  function startRound() {
    const question = nextQuestion();
    const round = {
      id: "round-" + Date.now().toString(36),
      prompt: question.prompt,
      a: question.a,
      b: question.b,
      deckLabel: question.deckLabel,
      revealed: false
    };
    state.round = round;
    state.votes = {};
    state.status = "New round. Cast your vote.";
    keepScreenOn(true);
    sendEvent(eventRoundStarted, {
      roundId: round.id,
      deckId: state.deckId,
      deckLabel: round.deckLabel,
      prompt: round.prompt,
      a: round.a,
      b: round.b
    });
    render();
  }

  function castVote(choice) {
    if (!state.round) {
      toast("Start a round first");
      return;
    }
    const normalized = choice === "B" ? "B" : "A";
    state.votes[state.memberId] = normalized;
    state.status = "Vote locked for " + normalized + ".";
    sendEvent(eventVoteCast, {
      roundId: state.round.id,
      choice: normalized
    });
    render();
  }

  function voteCounts() {
    let a = 0;
    let b = 0;
    Object.keys(state.votes).forEach(function (id) {
      if (state.votes[id] === "B") {
        b += 1;
      } else {
        a += 1;
      }
    });
    return { a: a, b: b, total: a + b };
  }

  function revealVotes(broadcast) {
    if (!state.round) {
      toast("Start a round first");
      return;
    }
    const counts = voteCounts();
    state.round.revealed = true;
    state.history.unshift({
      prompt: state.round.prompt,
      a: state.round.a,
      b: state.round.b,
      aVotes: counts.a,
      bVotes: counts.b,
      at: new Date().toLocaleTimeString()
    });
    state.history = state.history.slice(0, 6);
    state.status = "Votes revealed.";
    keepScreenOn(false);
    if (broadcast !== false) {
      sendEvent(eventVotesRevealed, { roundId: state.round.id });
    }
    render();
  }

  function startSolo() {
    state.mode = "play";
    state.role = "solo";
    state.memberId = memberId();
    state.memberName = "You";
    state.roomId = "";
    state.players = {};
    addPlayer(state.memberId, state.memberName);
    state.status = "Quick play ready.";
    stopPolling();
    startRound();
  }

  function startHost(name) {
    state.mode = "play";
    state.role = "host";
    state.memberId = memberId();
    state.memberName = String(name || "Host").trim().slice(0, 32) || "Host";
    state.roomId = roomCode();
    state.players = {};
    state.votes = {};
    addPlayer(state.memberId, state.memberName);
    state.status = "Creating room...";
    bridge("room.create", {
      roomId: state.roomId,
      memberId: state.memberId
    }).then(function (result) {
      if (result && result.roomId) {
        state.roomId = result.roomId;
      }
      state.status = "Share room " + state.roomId + " with nearby players.";
      storageSet(storageKey, JSON.stringify({ roomId: state.roomId, name: state.memberName }));
      sendEvent(eventSessionCreated, {});
      startPolling();
      render();
    });
    render();
  }

  function joinRoom(roomId, name) {
    const cleanRoom = safeId(roomId, "");
    if (!cleanRoom) {
      toast("Enter a room code first");
      return;
    }
    state.mode = "play";
    state.role = "player";
    state.memberId = memberId();
    state.memberName = String(name || "Player").trim().slice(0, 32) || "Player";
    state.roomId = cleanRoom;
    state.status = "Joining room...";
    addPlayer(state.memberId, state.memberName);
    bridge("room.join", {
      roomId: state.roomId,
      memberId: state.memberId
    }).then(function () {
      state.status = "Joined " + state.roomId + ". Wait for the next round.";
      storageSet(storageKey, JSON.stringify({ roomId: state.roomId, name: state.memberName }));
      sendEvent(eventPlayerJoined, {});
      startPolling();
      render();
    });
    render();
  }

  function field(label, id, value) {
    const wrap = el("label", "field");
    const text = el("span", "", label);
    const input = document.createElement("input");
    input.id = id;
    input.value = value || "";
    wrap.appendChild(text);
    wrap.appendChild(input);
    return { wrap: wrap, input: input };
  }

  function deckField() {
    const wrap = el("label", "field");
    wrap.appendChild(el("span", "", "Deck"));
    const select = document.createElement("select");
    decks.forEach(function (item) {
      const option = document.createElement("option");
      option.value = item.id;
      option.textContent = item.label;
      option.selected = item.id === state.deckId;
      select.appendChild(option);
    });
    select.addEventListener("change", function () {
      state.deckId = select.value;
      state.roundIndex = 0;
      render();
    });
    wrap.appendChild(select);
    return wrap;
  }

  function renderShell() {
    document.body.innerHTML = "";
    if (!document.querySelector("link[data-wyr-style]")) {
      const link = document.createElement("link");
      link.rel = "stylesheet";
      link.href = "assets/style.css";
      link.setAttribute("data-wyr-style", "true");
      document.head.appendChild(link);
    }
    const app = el("main", "wyrApp");
    const topbar = el("section", "topbar");
    const brand = el("div", "brand");
    const mark = el("img");
    mark.alt = "";
    mark.src = "assets/would-you-rather-icon.png";
    const titleWrap = el("div");
    titleWrap.appendChild(el("h1", "", "Would You Rather"));
    titleWrap.appendChild(el("div", "helper", "Safe votes for nearby friends."));
    brand.appendChild(mark);
    brand.appendChild(titleWrap);
    topbar.appendChild(brand);
    topbar.appendChild(el("div", "roomBadge", state.roomId || "Local"));
    app.appendChild(topbar);
    const hero = el("section", "hero");
    const heroImage = el("img", "heroImage");
    heroImage.alt = "";
    heroImage.src = "assets/would-you-rather-header.webp";
    hero.appendChild(heroImage);
    app.appendChild(hero);
    document.body.appendChild(app);
    return app;
  }

  function modeButton(title, body, onClick) {
    const button = el("button", "modeButton");
    button.appendChild(el("strong", "", title));
    button.appendChild(el("span", "", body));
    button.addEventListener("click", onClick);
    return button;
  }

  function renderHome(app) {
    const surface = el("section", "surface");
    const modes = el("div", "modeGrid");
    modes.appendChild(modeButton("Quick Play", "One device, reveal votes at the table.", startSolo));

    const setup = el("div", "joinGrid");
    const hostName = field("Host name", "host-name", state.memberName || "Host");
    const roomInput = field("Room code", "room-code", state.roomId || "");
    const playerName = field("Player name", "player-name", state.memberName || "Player");
    const hostButton = el("button", "primaryButton", "Create Room");
    hostButton.addEventListener("click", function () {
      startHost(hostName.input.value);
    });
    const joinButton = el("button", "secondaryButton", "Join Room");
    joinButton.addEventListener("click", function () {
      joinRoom(roomInput.input.value, playerName.input.value);
    });
    const hostBox = el("div", "controlStack");
    hostBox.appendChild(hostName.wrap);
    hostBox.appendChild(hostButton);
    const joinBox = el("div", "controlStack");
    joinBox.appendChild(roomInput.wrap);
    joinBox.appendChild(playerName.wrap);
    joinBox.appendChild(joinButton);
    setup.appendChild(hostBox);
    setup.appendChild(joinBox);

    modes.appendChild(modeButton("Host Room", "Create a LAN room and reveal results.", function () {
      hostName.input.focus();
    }));
    modes.appendChild(modeButton("Join Room", "Enter the code and cast votes.", function () {
      roomInput.input.focus();
    }));

    surface.appendChild(deckField());
    surface.appendChild(modes);
    surface.appendChild(setup);
    surface.appendChild(el("p", "status", state.status));
    app.appendChild(surface);
  }

  function renderChoice(choice, label, text) {
    const counts = voteCounts();
    const total = Math.max(1, counts.total);
    const count = label === "A" ? counts.a : counts.b;
    const selected = state.votes[state.memberId] === label;
    const card = el("section", "choiceCard choice" + label);
    card.appendChild(el("div", "choiceLabel", label));
    card.appendChild(el("p", "choiceText", text));
    if (state.round && state.round.revealed) {
      const percent = Math.round((count / total) * 100);
      const meta = el("div", "voteMeta", count + " votes · " + percent + "%");
      const bar = el("div", "resultBar");
      const fill = el("div", "resultFill");
      fill.style.width = percent + "%";
      bar.appendChild(fill);
      card.appendChild(meta);
      card.appendChild(bar);
    } else {
      const button = el("button", "choiceButton" + (selected ? " selected" : ""), selected ? "Selected" : "Vote " + label);
      button.addEventListener("click", function () {
        castVote(choice);
      });
      card.appendChild(button);
    }
    return card;
  }

  function renderGame(app) {
    const surface = el("section", "surface playGrid");
    const roundCard = el("section", "roundCard");
    const header = el("div", "roundHeader");
    header.appendChild(el("div", "roundTitle", state.round ? state.round.deckLabel : deck().label));
    header.appendChild(el("div", "voteMeta", state.round && state.round.revealed ? "Revealed" : "Voting"));
    roundCard.appendChild(header);
    roundCard.appendChild(el("p", "question", state.round ? state.round.prompt : "would you rather"));
    const choices = el("div", "choiceGrid");
    choices.appendChild(renderChoice("A", "A", state.round ? state.round.a : "Choice A"));
    choices.appendChild(renderChoice("B", "B", state.round ? state.round.b : "Choice B"));
    roundCard.appendChild(choices);
    surface.appendChild(roundCard);

    const controls = el("section", "controlStack");
    controls.appendChild(deckField());
    if (state.role !== "player") {
      const next = el("button", "primaryButton", state.round ? "Next Round" : "Start Round");
      next.addEventListener("click", startRound);
      controls.appendChild(next);
      const reveal = el("button", "secondaryButton", "Reveal Votes");
      reveal.addEventListener("click", function () {
        revealVotes(true);
      });
      controls.appendChild(reveal);
    } else {
      controls.appendChild(el("p", "status", "Player view. Vote, then wait for the host to reveal."));
    }
    const home = el("button", "secondaryButton", "Back to Modes");
    home.addEventListener("click", function () {
      state.mode = "";
      state.role = "";
      state.round = null;
      stopPolling();
      keepScreenOn(false);
      render();
    });
    controls.appendChild(home);
    controls.appendChild(el("p", "status", state.status));
    surface.appendChild(controls);
    app.appendChild(surface);
    app.appendChild(renderVotes());
    app.appendChild(renderHistory());
  }

  function renderVotes() {
    const panel = el("section", "votePanel");
    panel.appendChild(el("h2", "", "Players"));
    const list = el("div", "voteList");
    const rows = playerRows();
    if (!rows.length) {
      list.appendChild(el("p", "helper", "No players yet."));
    }
    rows.forEach(function (player) {
      const choice = state.votes[player.id] || "";
      const row = el("div", "voteRow");
      row.appendChild(el("div", "voteName", player.name));
      row.appendChild(el("div", "voteChip " + (choice === "A" ? "voteA" : choice === "B" ? "voteB" : "voteWaiting"), choice || "…"));
      list.appendChild(row);
    });
    panel.appendChild(list);
    return panel;
  }

  function renderHistory() {
    const panel = el("section", "history");
    panel.appendChild(el("h2", "", "Recent Rounds"));
    if (!state.history.length) {
      panel.appendChild(el("p", "helper", "No revealed rounds yet."));
      return panel;
    }
    state.history.forEach(function (item) {
      const row = el("div", "historyRow");
      const text = el("div");
      text.appendChild(el("div", "historyPrompt", item.a + " / " + item.b));
      text.appendChild(el("div", "historyMeta", item.aVotes + " A · " + item.bVotes + " B · " + item.at));
      row.appendChild(text);
      row.appendChild(el("strong", "", item.aVotes === item.bVotes ? "Tie" : item.aVotes > item.bVotes ? "A" : "B"));
      panel.appendChild(row);
    });
    return panel;
  }

  function render() {
    const app = renderShell();
    if (state.mode === "play") {
      renderGame(app);
    } else {
      renderHome(app);
    }
  }

  function boot() {
    storageGet(storageKey).then(function (value) {
      if (value) {
        try {
          const saved = JSON.parse(value);
          state.roomId = saved.roomId || "";
          state.memberName = saved.name || "";
        } catch (error) {
          state.roomId = "";
        }
      }
      render();
    });
  }

  window.addEventListener("beforeunload", function () {
    stopPolling();
    keepScreenOn(false);
  });

  boot();
})();
