import { useEffect, useState, useCallback } from "react";
import { useWebSocket } from "./useWebSocket";

interface PlayerInfo {
    discordId: string;
    username: string;
}

interface GameRoomState {
    gameState: unknown;
    players: PlayerInfo[];
    spectators: PlayerInfo[];
    roomStatus: "connecting" | "waiting" | "playing" | "finished" | "not_found";
    isSpectator: boolean;
    gameOver: { winner: string | null; reason: string } | null;
    error: string | null;
}

export function useGameRoom(roomId: string, userId: string) {
    const { send, subscribe, connected } = useWebSocket();
    const [state, setState] = useState<GameRoomState>({
        gameState: null,
        players: [],
        spectators: [],
        roomStatus: "connecting",
        isSpectator: false,
        gameOver: null,
        error: null,
    });

    useEffect(() => {
        if (!connected) return;

        send({ type: "JOIN_ROOM", roomId, as: "player" });

        const unsubscribe = subscribe((msg: any) => {
            if (msg.roomId && msg.roomId !== roomId) return;

            switch (msg.type) {
                case "GAME_STATE":
                    setState(prev => ({ ...prev, gameState: msg.state, roomStatus: "playing" }));
                    break;

                case "GAME_STARTED":
                    setState(prev => ({ ...prev, gameState: msg.state, roomStatus: "playing" }));
                    break;

                case "GAME_UPDATE":
                    setState(prev => ({ ...prev, gameState: msg.state }));
                    break;

                case "PLAYER_JOINED":
                    setState(prev => {
                        if (msg.as === "spectator") {
                            const isMe = msg.player.discordId === userId;
                            return {
                                ...prev,
                                spectators: [...prev.spectators.filter(s => s.discordId !== msg.player.discordId), msg.player],
                                isSpectator: isMe ? true : prev.isSpectator,
                                roomStatus: prev.roomStatus === "connecting" ? "waiting" : prev.roomStatus,
                            };
                        }
                        return {
                            ...prev,
                            players: [...prev.players.filter(p => p.discordId !== msg.player.discordId), msg.player],
                            roomStatus: prev.roomStatus === "connecting" ? "waiting" : prev.roomStatus,
                        };
                    });
                    break;

                case "PLAYER_LEFT":
                    setState(prev => ({
                        ...prev,
                        players: prev.players.filter(p => p.discordId !== msg.playerId),
                        spectators: prev.spectators.filter(s => s.discordId !== msg.playerId),
                    }));
                    break;

                case "GAME_ENDED":
                    setState(prev => ({
                        ...prev,
                        roomStatus: "finished",
                        gameOver: { winner: msg.winner, reason: msg.reason },
                    }));
                    break;

                case "ERROR":
                    if (msg.message === "Game already started" || msg.message === "Room is full") {
                        send({ type: "JOIN_ROOM", roomId, as: "spectator" });
                    } else if (msg.message === "Room not found") {
                        setState(prev => ({ ...prev, roomStatus: "not_found" }));
                    } else {
                        setState(prev => ({ ...prev, error: msg.message }));
                    }
                    break;
            }
        });

        return () => {
            send({ type: "LEAVE_ROOM", roomId });
            unsubscribe();
        };
    }, [roomId, connected, userId, send, subscribe]);

    const sendAction = useCallback((action: unknown) => {
        send({ type: "GAME_ACTION", roomId, action });
        setState(prev => ({ ...prev, error: null }));
    }, [roomId, send]);

    const leaveRoom = useCallback(() => {
        send({ type: "LEAVE_ROOM", roomId });
    }, [roomId, send]);

    return { ...state, sendAction, leaveRoom };
}
