/* QueueUp.gg — live party voting room */
const { useState, useEffect, useRef } = React;

function Avatar({ member, cls = "" }) {
  const bg = member.you
    ? "linear-gradient(135deg, var(--a1), var(--a2))"
    : `linear-gradient(135deg, oklch(0.64 0.2 ${member.hue}), oklch(0.6 0.18 ${(member.hue + 50) % 360}))`;
  const label = member.you ? "YOU" : member.name.slice(0, 2).toUpperCase();
  return <div className={`avatar ${cls}`} style={{ background: bg }} title={member.name}>{label}</div>;
}

// weighted pick: favor higher match score + the friend's own platform
function friendPick(candidates, member) {
  const weights = candidates.map((g) => {
    let w = Math.pow(g.score / 100, 4) + 0.04;
    if (member.plat && g.platforms.includes(member.plat)) w *= 1.7;
    if (g.free) w *= 1.12;
    return w;
  });
  const total = weights.reduce((a, b) => a + b, 0);
  let roll = Math.random() * total;
  for (let i = 0; i < candidates.length; i++) { roll -= weights[i]; if (roll <= 0) return candidates[i].id; }
  return candidates[candidates.length - 1].id;
}

function Confetti() {
  const pieces = Array.from({ length: 34 });
  const colors = ["var(--a1)", "var(--a2)", "var(--amber)", "var(--green)", "var(--a3)"];
  return (
    <div style={{ position: "fixed", inset: 0, pointerEvents: "none", zIndex: 70, overflow: "hidden" }}>
      {pieces.map((_, i) => (
        <span key={i} className="confetti" style={{
          left: `${Math.random() * 100}%`, background: colors[i % colors.length],
          animationDuration: `${1.8 + Math.random() * 1.6}s`, animationDelay: `${Math.random() * 0.5}s`,
          transform: `translateY(-20px) rotate(${Math.random() * 360}deg)`,
        }} />
      ))}
    </div>
  );
}

function VoteRoom({ prefs, results, onExit, onRestart }) {
  const candidates = results.slice(0, 5);
  const host = { name: "You", you: true, plat: prefs.platforms[0] || "PC", hue: 265 };

  const [members, setMembers] = useState([host, ...(prefs.party || [])]);
  const [votes, setVotes] = useState({});          // name -> gameId
  const [deciding, setDeciding] = useState([]);     // names currently "deciding"
  const [revealed, setRevealed] = useState(false);
  const timers = useRef([]);

  const scheduleFriendVotes = (friends, startAt) => {
    friends.forEach((m, i) => {
      const base = startAt + i * 1300 + Math.random() * 500;
      timers.current.push(setTimeout(() => setDeciding((d) => [...d, m.name]), base));
      timers.current.push(setTimeout(() => {
        const choice = friendPick(candidates, m);
        setVotes((v) => ({ ...v, [m.name]: choice }));
        setDeciding((d) => d.filter((n) => n !== m.name));
      }, base + 950));
    });
  };

  useEffect(() => {
    scheduleFriendVotes((prefs.party || []), 900);
    return () => timers.current.forEach(clearTimeout);
  }, []);

  // reveal once everyone has voted
  useEffect(() => {
    const voted = Object.keys(votes).length;
    if (members.length > 0 && voted >= members.length && !revealed) {
      const t = setTimeout(() => setRevealed(true), 750);
      return () => clearTimeout(t);
    }
  }, [votes, members, revealed]);

  const castMyVote = (gameId) => { if (!revealed) setVotes((v) => ({ ...v, You: gameId })); };

  const addFriends = () => {
    const taken = members.filter((m) => !m.you).map((m) => m.name);
    const fresh = FRIEND_POOL.filter((f) => !taken.includes(f.name)).slice(0, 3);
    if (!fresh.length) return;
    setMembers((m) => [...m, ...fresh]);
    scheduleFriendVotes(fresh, 500);
  };

  const reset = () => {
    timers.current.forEach(clearTimeout); timers.current = [];
    setVotes({}); setDeciding([]); setRevealed(false);
    scheduleFriendVotes(members.filter((m) => !m.you), 700);
  };

  // tallies
  const counts = {};
  candidates.forEach((g) => { counts[g.id] = []; });
  Object.entries(votes).forEach(([name, gid]) => { if (counts[gid]) counts[gid].push(name); });
  const memberByName = (n) => members.find((m) => m.name === n) || { name: n, hue: 200 };

  const votedCount = Object.keys(votes).length;
  const myVote = votes.You;
  const sorted = [...candidates].sort((a, b) => counts[b.id].length - counts[a.id].length || b.score - a.score);
  const winner = revealed ? sorted[0] : null;

  return (
    <div className="vote container">
      {revealed && <Confetti />}

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 6 }}>
        <button className="btn btn-ghost" onClick={onExit} style={{ padding: "8px 14px" }}>{Icons.arrowL({ size: 16 })} Back to picks</button>
        <div className="wz-step-label">Session {prefs.sessionId}</div>
      </div>

      {!revealed ? (
        <div className="vote-banner">
          <div className="vb-ico">{Icons.users({ size: 22 })}</div>
          <div style={{ flex: 1 }}>
            <div className="vb-title">Put it to a vote</div>
            <div className="vb-sub">Everyone picks their game — most votes wins. {members.length < 2 ? "Voting's better with a squad 👇" : "Tap your choice below."}</div>
          </div>
          {members.length < 4 && (
            <button className="btn btn-outline" onClick={addFriends} style={{ flexShrink: 0 }}>{Icons.users({ size: 16 })} Add friends</button>
          )}
        </div>
      ) : (
        <div className="winner-hero">
          <div className="wh-kicker">{Icons.crown({ size: 14 })} The squad has spoken</div>
          <h2>{winner.name} wins!</h2>
          <p className="muted" style={{ fontSize: 16, lineHeight: 1.5, maxWidth: 460, margin: "0 auto" }}>
            {counts[winner.id].length} of {members.length} {counts[winner.id].length === 1 ? "vote" : "votes"} — {winner.blurb}
          </p>
        </div>
      )}

      {/* roster */}
      <div className="vote-progress-row">
        <div className="roster">
          {members.map((m) => {
            const isDeciding = deciding.includes(m.name);
            const hasVoted = votes[m.name] != null;
            return (
              <div key={m.name} className={`voter-chip ${hasVoted ? "voted" : ""} ${isDeciding ? "deciding" : ""}`}>
                <Avatar member={m} cls="sm" />
                <div>
                  <div className="vc-name">{m.you ? "You" : m.name}</div>
                  <div className="vc-status">{hasVoted ? "voted ✓" : isDeciding ? "deciding…" : m.you ? "your turn" : "waiting"}</div>
                </div>
              </div>
            );
          })}
        </div>
        <div className="vp-label">{votedCount}/{members.length} voted</div>
      </div>

      {/* candidate rows */}
      <div className="vlist">
        {(revealed ? sorted : candidates).map((g) => {
          const voters = counts[g.id];
          const pct = members.length ? (voters.length / members.length) * 100 : 0;
          const isMine = myVote === g.id;
          const isWin = winner && winner.id === g.id;
          return (
            <div key={g.id} className={`card vrow ${isMine ? "mine" : ""} ${isWin ? "win" : ""}`}>
              <GameArt game={g} className="vrow-art" />
              <div className="vrow-main">
                <div className="vrow-name">
                  {g.name}
                  {isWin && <span className="win-badge">{Icons.trophy({ size: 12 })} Winner</span>}
                  {!isWin && isMine && <span className="chip chip-a1">Your pick</span>}
                </div>
                <div className="vrow-sub">{g.genres.slice(0, 2).join(" · ")} · {g.score}% match{g.free ? " · Free" : ""}</div>
                <div className="vtally">
                  <div className="vtally-track"><div className="vtally-fill" style={{ width: `${pct}%` }} /></div>
                  <div className="vtally-count">{voters.length} {voters.length === 1 ? "vote" : "votes"}</div>
                </div>
                <div className="voter-stack">
                  {voters.map((n) => <Avatar key={n} member={memberByName(n)} cls="xs" />)}
                </div>
              </div>
              {!revealed && (
                <div className="vrow-action">
                  <button className={`vote-btn ${isMine ? "mine" : ""}`} onClick={() => castMyVote(g.id)}>
                    {isMine ? <>{Icons.check({ size: 15 })} Voted</> : "Vote"}
                  </button>
                </div>
              )}
            </div>
          );
        })}
      </div>

      {/* footer actions */}
      <div style={{ display: "flex", gap: 12, justifyContent: "center", marginTop: 28, flexWrap: "wrap" }}>
        {revealed ? (
          <>
            <button className="btn btn-primary" onClick={reset}>{Icons.refresh({ size: 17 })} Re-vote</button>
            <button className="btn btn-ghost" onClick={onRestart}>{Icons.zap({ size: 17, fill: "currentColor", stroke: "none" })} New game night</button>
          </>
        ) : (
          <div className="muted" style={{ fontSize: 14, fontFamily: "var(--mono)" }}>
            {myVote ? "Waiting on the squad…" : "Cast your vote to get things rolling"}
          </div>
        )}
      </div>
    </div>
  );
}
window.VoteRoom = VoteRoom;
