import { z } from "zod";

export interface Room {
    id: string;
    gameSlug: string;
    host: string;
    players: string[];
    spectators: Set<string>;
    state: unknown;
    status: "waiting" | "playing" | "finished";
    createdAt: number;
}

export interface RoomSummary {
    id: string;
    gameSlug: string;
    gameName: string;
    host: string;
    playerCount: number;
    maxPlayers: number;
    spectatorCount: number;
    status: "waiting" | "playing" | "finished";
}

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

export const GameWsClientSchema = z.discriminatedUnion("type", [
    z.object({ type: z.literal("CREATE_ROOM"), gameType: z.string() }),
    z.object({
        type: z.literal("JOIN_ROOM"),
        roomId: z.string(),
        preferAs: z.enum(["player", "spectator"]),
        role: z.enum(["player", "admin"]).optional(),
    }),
    z.object({ type: z.literal("LEAVE_ROOM"), roomId: z.string() }),
    z.object({ type: z.literal("GAME_ACTION"), roomId: z.string(), action: z.record(z.unknown()) }),
    z.object({ type: z.literal("FILL_ROOM"), roomId: z.string() }),
]);

export type GameWsClientMessage = z.infer<typeof GameWsClientSchema>;

export type GameWsServerMessage =
    | { type: "ROOM_LIST_UPDATE"; rooms: RoomSummary[] }
    | { type: "GAME_STATE"; roomId: string; state: unknown }
    | { type: "GAME_UPDATE"; roomId: string; state: unknown }
    | { type: "PLAYER_JOINED"; roomId: string; player: PlayerInfo; joinedAs: "player" | "spectator" }
    | { type: "PLAYER_LEFT"; roomId: string; playerId: string }
    | { type: "GAME_STARTED"; roomId: string; state: unknown }
    | { type: "GAME_ENDED"; roomId: string; winner: string | null; reason: string }
    | { type: "ROOM_CREATED"; roomId: string; gameSlug: string }
    | { type: "JOIN_RESULT"; roomId: string; joinedAs: "player" | "spectator"; roomStatus: "waiting" | "playing" | "finished"; players: PlayerInfo[]; spectators: PlayerInfo[]; state?: unknown }
    | { type: "SESSION_REPLACED"; roomId: string }
    | { type: "ERROR"; message: string };
