/**
 * Game Adapter - Provides backward compatibility layer
 * This allows existing game code to work with the new Room/Session architecture
 * without requiring immediate refactoring of all game logic
 */

import type { GameRoom, GameSession, GameSessionMetadata } from "./gameMetadata";

/**
 * Proxy handler for Session objects
 * Intercepts property access to provide backward compatibility
 * Maps session.color -> session.metadata.color, etc.
 */
const sessionProxyHandler: ProxyHandler<GameSession> = {
  get(target: GameSession, prop: string | symbol): any {
    // Direct properties take precedence
    if (prop in target && prop !== "metadata") {
      return (target as any)[prop];
    }

    // Map game-specific properties to metadata
    if (typeof prop === "string") {
      const gameProps = ["color", "player", "resources"];
      if (gameProps.includes(prop)) {
        return target.metadata?.[prop as keyof GameSessionMetadata];
      }
    }

    return (target as any)[prop];
  },

  set(target: GameSession, prop: string | symbol, value: any): boolean {
    // Direct properties
    const directProps = [
      "id",
      "userId",
      "name",
      "ws",
      "live",
      "lastActive",
      "keepAlive",
      "connected",
      "has_media",
      "protected",
      "bot_run_id",
      "bot_provider_id",
      "bot_instance_id",
      "_initialSnapshotSent",
      "_getBatch",
      "_pendingMessage",
      "_pendingTimeout",
    ];

    if (typeof prop === "string" && directProps.includes(prop)) {
      (target as any)[prop] = value;
      return true;
    }

    // Game-specific properties go to metadata
    if (typeof prop === "string") {
      const gameProps = ["color", "player", "resources"];
      if (gameProps.includes(prop)) {
        if (!target.metadata) {
          target.metadata = {};
        }
        (target.metadata as any)[prop] = value;
        return true;
      }
    }

    // Unknown properties
    (target as any)[prop] = value;
    return true;
  },

  has(target: GameSession, prop: string | symbol): boolean {
    if (prop in target) return true;
    if (typeof prop === "string") {
      const gameProps = ["color", "player", "resources"];
      return gameProps.includes(prop) && target.metadata !== undefined;
    }
    return false;
  },
};

/**
 * Proxy handler for Game/Room objects
 * Maps game.players -> game.metadata.players, etc.
 */
const gameProxyHandler: ProxyHandler<GameRoom> = {
  get(target: GameRoom, prop: string | symbol): any {
    // Direct room properties
    const roomProps = ["id", "name", "sessions", "state", "created", "lastActivity", "private"];
    if (typeof prop === "string" && roomProps.includes(prop)) {
      return (target as any)[prop];
    }

    // Game properties from metadata
    if (typeof prop === "string" && target.metadata) {
      if (prop in target.metadata) {
        return (target.metadata as any)[prop];
      }
    }

    return (target as any)[prop];
  },

  set(target: GameRoom, prop: string | symbol, value: any): boolean {
    // Direct room properties
    const roomProps = ["id", "name", "sessions", "state", "created", "lastActivity", "private"];
    if (typeof prop === "string" && roomProps.includes(prop)) {
      (target as any)[prop] = value;
      return true;
    }

    // Game properties to metadata
    if (typeof prop === "string") {
      if (!target.metadata) {
        target.metadata = {} as any;
      }
      (target.metadata as any)[prop] = value;
      return true;
    }

    (target as any)[prop] = value;
    return true;
  },

  has(target: GameRoom, prop: string | symbol): boolean {
    const roomProps = ["id", "name", "sessions", "state", "created", "lastActivity", "private"];
    if (typeof prop === "string") {
      if (roomProps.includes(prop)) return true;
      if (target.metadata && prop in target.metadata) return true;
    }
    return false;
  },
};

/**
 * Wrap a session object with backward compatibility proxy
 */
export function wrapSession(session: GameSession): GameSession {
  return new Proxy(session, sessionProxyHandler);
}

/**
 * Wrap a game/room object with backward compatibility proxy
 */
export function wrapGame(game: GameRoom): GameRoom {
  return new Proxy(game, gameProxyHandler);
}

/**
 * Wrap all sessions in a game/room
 */
export function wrapGameSessions(game: GameRoom): GameRoom {
  const wrappedGame = wrapGame(game);

  // Wrap each session
  const wrappedSessions: Record<string, GameSession> = {};
  for (const id in game.sessions) {
    if (game.sessions[id]) {
      wrappedSessions[id] = wrapSession(game.sessions[id]);
    }
  }

  wrappedGame.sessions = wrappedSessions;
  return wrappedGame;
}

/**
 * Initialize metadata for a session if it doesn't exist
 */
export function ensureSessionMetadata(session: GameSession): void {
  if (!session.metadata) {
    session.metadata = {};
  }
}

/**
 * Initialize metadata for a game/room if it doesn't exist
 */
export function ensureGameMetadata(game: GameRoom): void {
  if (!game.metadata) {
    game.metadata = {
      developmentCards: [],
      players: {},
      placements: { corners: [], roads: [] },
      turn: {},
    } as any;
  }
}

/**
 * Helper to access session's game metadata safely
 */
export function getSessionGameData(session: GameSession): GameSessionMetadata {
  ensureSessionMetadata(session);
  return session.metadata!;
}

/**
 * Helper to access game's metadata safely
 */
export function getGameMetadata(game: GameRoom) {
  ensureGameMetadata(game);
  return game.metadata;
}
