/**
 * Game-specific metadata types
 * These extend the base Room/Session types with Settlers of Catan specific data
 */

import type { Player, Turn, Placements, DevelopmentCard } from "./types";

/**
 * Game-specific session metadata
 * This is stored in Session.metadata for each session
 */
export interface GameSessionMetadata {
  // Player association
  color?: string; // The color this session is playing as
  player?: Player; // Reference to the player object

  // Temporary resources (for trading, etc.)
  resources?: number;
}

/**
 * Game-specific room metadata
 * This is stored in Room.metadata for the game room
 */
export interface GameRoomMetadata {
  // Game data
  developmentCards: DevelopmentCard[];
  players: Record<string, Player>; // Keyed by color
  unselected?: any[]; // Sessions without color selection
  active?: number; // Number of active players

  // Game state
  rules?: any;
  step?: number;
  placements: Placements;
  turn: Turn;

  // Board setup
  pipOrder?: number[];
  tileOrder?: number[];
  borderOrder?: number[];
  tiles?: any[];
  pips?: any[];
  borders?: any[];

  // Game flow
  dice?: number[];
  chat?: any[];
  activities?: any[];
  playerOrder?: string[];
  direction?: string;
  turns?: number;

  // Game stats
  robber?: number;
  robberName?: string;
  longestRoad?: string | false;
  longestRoadLength?: number;
  largestArmy?: string | false;
  largestArmySize?: number;
  mostPorts?: string | false;
  mostDeveloped?: string | false;

  // Debug
  debug?: boolean;
  signature?: string;
  animationSeeds?: number[];

  // Timers
  turnTimer?: any;
}

/**
 * Helper type for a complete game room
 */
export type GameRoom = {
  id: string;
  name: string;
  sessions: Record<string, GameSession>;
  state: string;
  created: number;
  lastActivity: number;
  private?: boolean;
  metadata: GameRoomMetadata;
};

/**
 * Helper type for a game session
 */
export type GameSession = {
  id: string;
  userId?: number;
  name: string | null;
  ws?: any;
  live: boolean;
  lastActive: number;
  keepAlive?: any;
  connected: boolean;
  has_media: boolean;
  protected?: boolean;
  bot_run_id?: string | null;
  bot_provider_id?: string | null;
  bot_instance_id?: string | null;
  _initialSnapshotSent?: boolean;
  _getBatch?: { fields: Set<string>; timer?: any };
  _pendingMessage?: any;
  _pendingTimeout?: any;
  metadata?: GameSessionMetadata;
};

/**
 * Migration helpers to convert between old and new formats
 */

/**
 * Convert old Session to new format
 */
export function migrateSessionToNewFormat(oldSession: any): GameSession {
  const { color, player, resources, ...baseFields } = oldSession;

  return {
    ...baseFields,
    has_media: baseFields.has_media ?? true,
    name: baseFields.name ?? null,
    live: baseFields.live ?? false,
    connected: baseFields.connected ?? false,
    lastActive: baseFields.lastActive ?? Date.now(),
    metadata: {
      color,
      player,
      resources,
    },
  };
}

/**
 * Convert new Session to old format (for backward compatibility)
 */
export function migrateSessionToOldFormat(newSession: GameSession): any {
  const { metadata, ...baseFields } = newSession;

  return {
    ...baseFields,
    color: metadata?.color,
    player: metadata?.player,
    resources: metadata?.resources,
  };
}

/**
 * Convert old Game to new Room format
 */
export function migrateGameToRoomFormat(oldGame: any): GameRoom {
  const { sessions, id, ...gameFields } = oldGame;

  // Convert sessions
  const newSessions: Record<string, GameSession> = {};
  for (const sessionId in sessions) {
    newSessions[sessionId] = migrateSessionToNewFormat(sessions[sessionId]);
  }

  return {
    id: oldGame.id,
    name: oldGame.id, // Game ID is the room name
    sessions: newSessions,
    state: oldGame.state || "lobby",
    created: Date.now(),
    lastActivity: Date.now(),
    private: false,
    metadata: gameFields,
  };
}

/**
 * Convert new Room to old Game format (for backward compatibility)
 */
export function migrateRoomToGameFormat(room: GameRoom): any {
  const { metadata, sessions, ...roomFields } = room;

  // Convert sessions back
  const oldSessions: Record<string, any> = {};
  for (const sessionId in sessions) {
    if (sessions[sessionId]) {
      oldSessions[sessionId] = migrateSessionToOldFormat(sessions[sessionId]);
    }
  }

  return {
    ...roomFields,
    ...metadata,
    sessions: oldSessions,
  };
}
