import { RoomManager } from "./RoomManager";
import type { GameWsClientMessage, PlayerInfo } from "./types";
import { logger } from "@shared/lib/logger";

export const roomManager = new RoomManager();

interface WsContext {
    playerId: string;
    username: string;
    send: (data: string) => void;
    subscribe: (channel: string) => void;
    unsubscribe: (channel: string) => void;
    publish: (channel: string, data: string) => void;
}

export function handleGameMessage(msg: GameWsClientMessage, ctx: WsContext): void {
    switch (msg.type) {
        case "CREATE_ROOM": {
            const result = roomManager.createRoom(msg.gameType, ctx.playerId);
            if (!result.ok) {
                ctx.send(JSON.stringify({ type: "ERROR", message: result.error }));
                return;
            }
            ctx.subscribe(`room:${result.roomId}`);
            ctx.send(JSON.stringify({ type: "ROOM_CREATED", roomId: result.roomId, gameSlug: msg.gameType }));
            ctx.publish("lobby", JSON.stringify({ type: "ROOM_LIST_UPDATE", rooms: roomManager.listRooms() }));
            logger.debug("games", `Room created: ${result.roomId} (${msg.gameType}) by ${ctx.playerId}`);
            break;
        }

        case "JOIN_ROOM": {
            const result = roomManager.joinRoom(msg.roomId, ctx.playerId, msg.as);
            if (!result.ok) {
                ctx.send(JSON.stringify({ type: "ERROR", message: result.error }));
                return;
            }

            ctx.subscribe(`room:${msg.roomId}`);
            const playerInfo: PlayerInfo = { discordId: ctx.playerId, username: ctx.username };
            ctx.publish(`room:${msg.roomId}`, JSON.stringify({ type: "PLAYER_JOINED", roomId: msg.roomId, player: playerInfo, as: msg.as }));

            if (result.started) {
                const spectatorView = roomManager.getSpectatorView(msg.roomId);
                ctx.publish(`room:${msg.roomId}`, JSON.stringify({ type: "GAME_STARTED", roomId: msg.roomId, state: spectatorView }));
            } else {
                const room = roomManager.getRoom(msg.roomId);
                if (room && room.status === "playing") {
                    const view = msg.as === "spectator"
                        ? roomManager.getSpectatorView(msg.roomId)
                        : roomManager.getPlayerView(msg.roomId, ctx.playerId);
                    ctx.send(JSON.stringify({ type: "GAME_STATE", roomId: msg.roomId, state: view }));
                }
            }

            ctx.publish("lobby", JSON.stringify({ type: "ROOM_LIST_UPDATE", rooms: roomManager.listRooms() }));
            break;
        }

        case "LEAVE_ROOM": {
            roomManager.leaveRoom(msg.roomId, ctx.playerId);
            ctx.unsubscribe(`room:${msg.roomId}`);
            ctx.publish(`room:${msg.roomId}`, JSON.stringify({ type: "PLAYER_LEFT", roomId: msg.roomId, playerId: ctx.playerId }));
            ctx.publish("lobby", JSON.stringify({ type: "ROOM_LIST_UPDATE", rooms: roomManager.listRooms() }));
            break;
        }

        case "GAME_ACTION": {
            const result = roomManager.handleAction(msg.roomId, ctx.playerId, msg.action);
            if (!result.ok) {
                ctx.send(JSON.stringify({ type: "ERROR", message: result.error }));
                return;
            }

            const spectatorView = roomManager.getSpectatorView(msg.roomId);
            ctx.publish(`room:${msg.roomId}`, JSON.stringify({ type: "GAME_UPDATE", roomId: msg.roomId, state: spectatorView }));

            if (result.gameOver) {
                ctx.publish(`room:${msg.roomId}`, JSON.stringify({
                    type: "GAME_ENDED",
                    roomId: msg.roomId,
                    winner: result.gameOver.winner,
                    reason: result.gameOver.reason,
                }));
                ctx.publish("lobby", JSON.stringify({ type: "ROOM_LIST_UPDATE", rooms: roomManager.listRooms() }));
            }
            break;
        }
    }
}
