import { creditWallet, debitWallet, writeAuditLog } from './db.ts';

export type GameType = 'slots_tournament' | 'spinning_race' | 'daily_battle' | 'team_challenge';
export type GameStatus = 'waiting' | 'in_progress' | 'completed' | 'cancelled';

export interface MultiplayerGame {
  id: string;
  type: GameType;
  status: GameStatus;
  title: string;
  description: string;
  icon: string;
  entryFee: number;
  maxPlayers: number;
  currentPlayers: number;
  prizePool: number;
  startTime: Date;
  endTime: Date;
  createdAt: Date;
}

export interface GameParticipant {
  id: string;
  gameId: string;
  playerId: number;
  playerName: string;
  score: number;
  rank?: number;
  prizeWon?: number;
  joinedAt: Date;
  completedAt?: Date;
}

/**
 * Multiplayer Games Manager
 */
export class MultiplayerGamesManager {
  private games: Map<string, MultiplayerGame> = new Map();
  private participants: Map<string, GameParticipant[]> = new Map(); // gameId -> participants
  private playerGames: Map<number, string[]> = new Map(); // playerId -> gameIds

  /**
   * Create new game
   */
  async createGame(
    type: GameType,
    title: string,
    description: string,
    entryFee: number,
    maxPlayers: number,
    durationMinutes: number
  ): Promise<MultiplayerGame> {
    const now = new Date();
    const game: MultiplayerGame = {
      id: `game_${Date.now()}_${Math.random().toString(36).substring(7)}`,
      type,
      status: 'waiting',
      title,
      description,
      icon: this.getGameIcon(type),
      entryFee,
      maxPlayers,
      currentPlayers: 0,
      prizePool: 0,
      startTime: new Date(now.getTime() + 5 * 60 * 1000), // Start in 5 minutes
      endTime: new Date(now.getTime() + (5 + durationMinutes) * 60 * 1000),
      createdAt: now,
    };

    this.games.set(game.id, game);
    this.participants.set(game.id, []);

    await writeAuditLog({
      actorId: 0,
      actorRole: 'system',
      action: 'multiplayer_game_created',
      category: 'game',
      details: { gameId: game.id, gameType: type, title },
    });

    return game;
  }

  /**
   * Get game icon
   */
  private getGameIcon(type: GameType): string {
    switch (type) {
      case 'slots_tournament':
        return '🎰';
      case 'spinning_race':
        return '🏁';
      case 'daily_battle':
        return '⚔️';
      case 'team_challenge':
        return '👥';
      default:
        return '🎮';
    }
  }

  /**
   * Join game
   */
  async joinGame(playerId: number, playerName: string, gameId: string): Promise<{ success: boolean; message: string }> {
    const game = this.games.get(gameId);
    if (!game) {
      return { success: false, message: 'Game not found' };
    }

    if (game.status !== 'waiting') {
      return { success: false, message: 'Game is not accepting players' };
    }

    if (game.currentPlayers >= game.maxPlayers) {
      return { success: false, message: 'Game is full' };
    }

    // Check if already joined
    const participants = this.participants.get(gameId) || [];
    if (participants.some((p) => p.playerId === playerId)) {
      return { success: false, message: 'Already joined this game' };
    }

    // Debit entry fee
    const debitResult = await debitWallet(playerId, 'SC', game.entryFee, 'game_entry', `Entry fee for ${game.title}`, String(playerId));

    if (!debitResult) {
      return { success: false, message: 'Insufficient balance' };
    }

    // Add participant
    const participant: GameParticipant = {
      id: `part_${Date.now()}_${Math.random().toString(36).substring(7)}`,
      gameId,
      playerId,
      playerName,
      score: 0,
      joinedAt: new Date(),
    };

    participants.push(participant);
    game.currentPlayers++;
    game.prizePool += game.entryFee;

    if (!this.playerGames.has(playerId)) {
      this.playerGames.set(playerId, []);
    }
    this.playerGames.get(playerId)!.push(gameId);

    // Auto-start if full
    if (game.currentPlayers >= game.maxPlayers) {
      game.status = 'in_progress';
      game.startTime = new Date();
    }

    await writeAuditLog({
      actorId: playerId,
      actorRole: 'user',
      action: 'multiplayer_game_joined',
      category: 'game',
      details: { gameId, gameType: game.type, entryFee: game.entryFee },
    });

    return { success: true, message: 'Successfully joined game' };
  }

  /**
   * Update participant score
   */
  async updateScore(gameId: string, playerId: number, scoreIncrement: number): Promise<void> {
    const participants = this.participants.get(gameId) || [];
    const participant = participants.find((p) => p.playerId === playerId);

    if (participant) {
      participant.score += scoreIncrement;
    }
  }

  /**
   * Complete game and distribute prizes
   */
  async completeGame(gameId: string): Promise<void> {
    const game = this.games.get(gameId);
    if (!game) return;

    game.status = 'completed';
    game.endTime = new Date();

    const participants = this.participants.get(gameId) || [];

    // Sort by score descending
    participants.sort((a, b) => b.score - a.score);

    // Distribute prizes (60% to 1st, 30% to 2nd, 10% to 3rd)
    const prizeDistribution = [0.6, 0.3, 0.1];

    for (let i = 0; i < Math.min(3, participants.length); i++) {
      const participant = participants[i];
      const prizeAmount = Math.floor(game.prizePool * prizeDistribution[i]);

      participant.rank = i + 1;
      participant.prizeWon = prizeAmount;
      participant.completedAt = new Date();

      // Credit prize
      if (prizeAmount > 0) {
        await creditWallet(
          participant.playerId,
          'SC',
          prizeAmount,
          'game_prize',
          `Prize for ${game.title} - Rank #${i + 1}`,
          String(participant.playerId)
        );
      }
    }

    // Mark remaining as completed
    for (let i = 3; i < participants.length; i++) {
      participants[i].rank = i + 1;
      participants[i].completedAt = new Date();
    }

    await writeAuditLog({
      actorId: 0,
      actorRole: 'system',
      action: 'multiplayer_game_completed',
      category: 'game',
      details: { gameId, gameType: game.type, prizePool: game.prizePool },
    });
  }

  /**
   * Get game details
   */
  async getGame(gameId: string): Promise<MultiplayerGame | null> {
    return this.games.get(gameId) || null;
  }

  /**
   * Get game participants
   */
  async getGameParticipants(gameId: string): Promise<GameParticipant[]> {
    const participants = this.participants.get(gameId) || [];
    return participants.sort((a, b) => b.score - a.score);
  }

  /**
   * Get active games
   */
  async getActiveGames(): Promise<MultiplayerGame[]> {
    const now = new Date();
    return Array.from(this.games.values()).filter(
      (g) => g.status === 'waiting' || (g.status === 'in_progress' && g.endTime > now)
    );
  }

  /**
   * Get games by type
   */
  async getGamesByType(type: GameType): Promise<MultiplayerGame[]> {
    return Array.from(this.games.values()).filter((g) => g.type === type);
  }

  /**
   * Get player's games
   */
  async getPlayerGames(playerId: number): Promise<Array<MultiplayerGame & { participant: GameParticipant }>> {
    const gameIds = this.playerGames.get(playerId) || [];
    const playerGames: Array<MultiplayerGame & { participant: GameParticipant }> = [];

    for (const gameId of gameIds) {
      const game = this.games.get(gameId);
      const participants = this.participants.get(gameId) || [];
      const participant = participants.find((p) => p.playerId === playerId);

      if (game && participant) {
        playerGames.push({ ...game, participant });
      }
    }

    return playerGames;
  }

  /**
   * Get leaderboard for game
   */
  async getGameLeaderboard(gameId: string): Promise<Array<{
    rank: number;
    playerName: string;
    score: number;
    prizeWon?: number;
  }>> {
    const participants = await this.getGameParticipants(gameId);

    return participants.map((p, index) => ({
      rank: index + 1,
      playerName: p.playerName,
      score: p.score,
      prizeWon: p.prizeWon,
    }));
  }

  /**
   * Get game stats
   */
  async getStats(): Promise<{
    totalGames: number;
    activeGames: number;
    completedGames: number;
    totalPrizePool: number;
    totalParticipants: number;
  }> {
    let activeGames = 0;
    let completedGames = 0;
    let totalPrizePool = 0;
    let totalParticipants = 0;

    for (const game of this.games.values()) {
      if (game.status === 'waiting' || game.status === 'in_progress') {
        activeGames++;
      } else if (game.status === 'completed') {
        completedGames++;
      }

      totalPrizePool += game.prizePool;
    }

    for (const participants of this.participants.values()) {
      totalParticipants += participants.length;
    }

    return {
      totalGames: this.games.size,
      activeGames,
      completedGames,
      totalPrizePool,
      totalParticipants,
    };
  }

  /**
   * Create default games
   */
  async createDefaultGames(): Promise<void> {
    // Slots Tournament
    await this.createGame(
      'slots_tournament',
      'Daily Slots Tournament',
      'Compete in a fast-paced slots tournament. Highest score wins!',
      100,
      20,
      30
    );

    // Spinning Race
    await this.createGame(
      'spinning_race',
      'Spinning Race Challenge',
      'Race against other players. First to 50 wins takes the prize!',
      50,
      10,
      15
    );

    // Daily Battle
    await this.createGame(
      'daily_battle',
      'Daily Battle Royale',
      'Head-to-head battles. Eliminate opponents to climb the ranks!',
      200,
      8,
      45
    );

    // Team Challenge
    await this.createGame(
      'team_challenge',
      'Team Challenge',
      'Form teams and compete together. Teamwork makes the dream work!',
      75,
      16,
      30
    );
  }
}

export const multiplayerGamesManager = new MultiplayerGamesManager();
