// Turnix — App shell: multiplayer state machine

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "bgMode": "animated",
  "particles": true,
  "glow": 1,
  "density": "comfy",
  "impostorAccent": "#b48bff",
  "letterAccent": "#4ea1ff",
  "wrongAccent": "#ff8b4a"
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [route, setRoute] = React.useState("home");
  const [nick, setNick] = React.useState(() => localStorage.getItem("tx_nick") || "");
  const [roomState, setRoomState] = React.useState(null);
  const [roomCode, setRoomCode] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState(null);

  const unsubRoom = React.useRef(null);
  const unsubActs = React.useRef(null);
  const codeRef = React.useRef(null);
  const isHostRef = React.useRef(false);

  const isHost = roomState?.hostId === MY_ID;
  isHostRef.current = isHost;

  React.useEffect(() => {
    if (nick) localStorage.setItem("tx_nick", nick);
  }, [nick]);

  React.useEffect(() => {
    document.documentElement.dataset.density = t.density;
    document.documentElement.style.setProperty("--glow-strength", t.glow);
    document.documentElement.style.setProperty("--p-impostor", t.impostorAccent);
    document.documentElement.style.setProperty("--p-letter", t.letterAccent);
    document.documentElement.style.setProperty("--p-wrong", t.wrongAccent);
  }, [t]);

  const routeFromPhase = (phase, game) => {
    if (phase === "lobby") return "lobby";
    if (phase === "game") return game;
    if (phase === "results") return "results";
    if (phase === "final") return "final";
    return "lobby";
  };

  const enterRoom = (code, state) => {
    codeRef.current = code;
    setRoomCode(code);
    setRoomState(state);
    setRoute(routeFromPhase(state.phase, state.game));

    if (unsubRoom.current) unsubRoom.current();
    unsubRoom.current = txSubscribeToRoom(code, newState => {
      setRoomState(newState);
      setRoute(routeFromPhase(newState.phase, newState.game));
    });
  };

  // Host subscribes to incoming player actions and processes them
  React.useEffect(() => {
    if (!isHost || !roomCode) return;
    if (unsubActs.current) unsubActs.current();
    unsubActs.current = txSubscribeToActions(roomCode, action => {
      setRoomState(prev => {
        if (!prev) return prev;
        const next = processAction(prev, action);
        txUpdateRoomState(codeRef.current, next);
        return next;
      });
    });
    return () => { if (unsubActs.current) { unsubActs.current(); unsubActs.current = null; } };
  }, [isHost, roomCode]);

  // sendAction: host processes locally; non-host broadcasts to host
  const sendAction = React.useCallback(action => {
    const code = codeRef.current;
    if (!code) return;
    if (isHostRef.current) {
      setRoomState(prev => {
        if (!prev) return prev;
        const next = processAction(prev, { ...action, playerId: MY_ID });
        txUpdateRoomState(code, next);
        return next;
      });
    } else {
      txBroadcastAction(code, action);
    }
  }, []);

  const goHome = () => {
    if (codeRef.current) {
      txLeaveRoom(codeRef.current);
      if (unsubRoom.current) { unsubRoom.current(); unsubRoom.current = null; }
      if (unsubActs.current) { unsubActs.current(); unsubActs.current = null; }
    }
    codeRef.current = null;
    setRoomCode(null);
    setRoomState(null);
    setRoute("home");
    setError(null);
  };

  const handleCreate = async ({ game, maxPlayers, rounds }) => {
    setLoading(true);
    setError(null);
    try {
      const code = randomCode();
      const state = await txCreateRoom({ code, game, maxPlayers, rounds, playerName: nick || "Host" });
      enterRoom(code, state);
    } catch (e) {
      setError(e.message || "Failed to create room");
    } finally {
      setLoading(false);
    }
  };

  const handleJoin = async (code) => {
    setLoading(true);
    setError(null);
    try {
      const state = await txJoinRoom({ code: code.toUpperCase(), playerName: nick || "Player" });
      enterRoom(code.toUpperCase(), state);
    } catch (e) {
      setError(e.message || "Room not found");
    } finally {
      setLoading(false);
    }
  };

  const accent = roomState?.game ? GAMES[roomState.game]?.accentRaw : null;

  const gameProps = {
    roomState,
    isHost,
    myId: MY_ID,
    onAction: sendAction,
    onAdvance: () => sendAction({ type: "advance" }),
    onNextRound: () => sendAction({ type: "nextRound" }),
    onPlayAgain: () => sendAction({ type: "playAgain" }),
    onLeave: goHome,
  };

  return (
    <>
      <Background mode={t.bgMode} particles={t.particles} accent={accent} />
      <main style={{ position: "relative", zIndex: 1, height: "100%", display: "flex", flexDirection: "column" }}>

        {error && (
          <div style={{
            position: "fixed", top: 16, left: "50%", transform: "translateX(-50%)",
            background: "rgba(255,84,112,0.15)", border: "1px solid rgba(255,84,112,0.4)",
            color: "#ff8aa1", padding: "10px 20px", borderRadius: 10, zIndex: 100,
            fontSize: 14, fontWeight: 500, display: "flex", alignItems: "center", gap: 12,
          }}>
            {error}
            <button onClick={() => setError(null)} style={{ background: "none", border: 0, color: "inherit", cursor: "pointer", fontSize: 16 }}>✕</button>
          </div>
        )}

        {loading && (
          <div style={{
            position: "fixed", inset: 0, zIndex: 90,
            display: "flex", alignItems: "center", justifyContent: "center",
            background: "rgba(7,8,12,0.75)",
          }}>
            <div style={{ color: "var(--fg-1)", fontSize: 14, letterSpacing: ".06em" }}>Connecting…</div>
          </div>
        )}

        {route === "home" && (
          <HomeScreen nick={nick} setNick={setNick}
            onPlay={gameId => handleCreate({ game: gameId, maxPlayers: 8, rounds: 5 })}
            onCreate={() => setRoute("create")}
            onJoin={() => setRoute("join")} />
        )}
        {route === "create" && (
          <CreateScreen onBack={() => setRoute("home")} onCreate={handleCreate} />
        )}
        {route === "join" && (
          <JoinScreen onBack={() => setRoute("home")} onJoin={handleJoin} />
        )}
        {route === "lobby"    && roomState && <LobbyScreen    {...gameProps} />}
        {route === "impostor" && roomState && <ImpostorScreen {...gameProps} />}
        {route === "letter"   && roomState && <LetterScreen   {...gameProps} />}
        {route === "wrong"    && roomState && <WrongScreen    {...gameProps} />}
        {(route === "results" || route === "final") && roomState && (
          <ResultsScreen {...gameProps} isFinal={route === "final"} />
        )}
      </main>

      <TweaksPanel title="Tweaks · Turnix">
        <TweakSection label="Background" />
        <TweakRadio label="Mode" value={t.bgMode}
          options={[{value:"animated",label:"Anim"},{value:"static",label:"Static"},{value:"off",label:"Flat"}]}
          onChange={v => setTweak("bgMode", v)} />
        <TweakToggle label="Particles" value={t.particles} onChange={v => setTweak("particles", v)} />
        <TweakSlider label="Glow" value={t.glow} min={0} max={2} step={0.1} onChange={v => setTweak("glow", v)} />
        <TweakSection label="Density" />
        <TweakRadio label="Spacing" value={t.density} options={["compact","comfy"]} onChange={v => setTweak("density", v)} />
        <TweakSection label="Game accents" />
        <TweakColor label="Word Impostor" value={t.impostorAccent} onChange={v => setTweak("impostorAccent", v)} />
        <TweakColor label="Letter Game"   value={t.letterAccent}   onChange={v => setTweak("letterAccent", v)} />
        <TweakColor label="Wrong Answer"  value={t.wrongAccent}    onChange={v => setTweak("wrongAccent", v)} />
        <TweakSection label="Room" />
        {roomCode && (
          <div style={{ fontFamily: "var(--font-mono)", fontSize: 13, color: "#29261b", letterSpacing: ".1em", fontWeight: 700 }}>
            Code: {roomCode}
          </div>
        )}
        <TweakButton label="← Home" onClick={goHome} secondary />
      </TweaksPanel>
    </>
  );
}

function randomCode() {
  const A = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
  let out = "";
  for (let i = 0; i < 4; i++) out += A[Math.floor(Math.random() * A.length)];
  return out;
}

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