import { Room, Client } from 'colyseus';
import { Schema, type, MapSchema } from '@colyseus/schema';

class PlayerState extends Schema {
  @type('string') id: string;
  @type('string') username: string;
  @type('number') x: number = 0;
  @type('number') y: number = 1.6; // Eye height
  @type('number') z: number = 0;
  @type('number') rotationY: number = 0;
  @type('number') rotationX: number = 0;
  @type('number') health: number = 100;
  @type('number') kills: number = 0;
  @type('string') weapon: string = 'pistol';
  @type('boolean') isAlive: boolean = true;
}

class GameState extends Schema {
  @type({ map: PlayerState }) players = new MapSchema<PlayerState>();
  @type('string') mapName: string = 'arena_01';
  @type('number') gameTime: number = 0;
  @type('string') status: string = 'waiting'; // 'waiting', 'active', 'ended'
}

export class GameRoom extends Room<GameState> {
  maxClients = 2;
  private matchStartTime: number = 0;
  private gameLoop: NodeJS.Timer | null = null;

  onCreate(options: any) {
    console.log('Game room created');
    this.setState(new GameState());
    this.state.mapName = options.mapName || 'arena_01';
  }

  onJoin(client: Client, options: any) {
    const username = options.username || `Player_${client.sessionId.slice(0, 6)}`;
    
    console.log(`${username} joined game room`);
    
    // Create player state
    const playerState = new PlayerState();
    playerState.id = client.sessionId;
    playerState.username = username;
    
    // Alternate spawn positions
    if (this.clients.length === 1) {
      playerState.x = -5;
      playerState.z = 0;
    } else {
      playerState.x = 5;
      playerState.z = 0;
    }
    
    this.state.players.set(client.sessionId, playerState);

    // If 2 players, start game
    if (this.clients.length === 2) {
      this.startGame();
    }
  }

  onMessage(client: Client, type: string, message: any) {
    if (type === 'player_update') {
      const player = this.state.players.get(client.sessionId);
      if (player) {
        player.x = message.x;
        player.y = message.y;
        player.z = message.z;
        player.rotationY = message.rotationY;
        player.rotationX = message.rotationX;
        player.weapon = message.weapon;
      }
    } else if (type === 'shot_fired') {
      // Relay shot to opponent
      const opponent = Array.from(this.clients).find((c) => c.sessionId !== client.sessionId);
      if (opponent) {
        opponent.send('shot_fired', {
          shooterId: client.sessionId,
          position: message.position,
          direction: message.direction,
          weapon: message.weapon,
        });
      }
    } else if (type === 'hit_registered') {
      // Handle hit and update player health
      const hitPlayer = this.state.players.get(message.targetId);
      const shooter = this.state.players.get(client.sessionId);
      
      if (hitPlayer && shooter) {
        const damage = message.damage || 25;
        hitPlayer.health -= damage;
        
        if (hitPlayer.health <= 0) {
          hitPlayer.health = 0;
          hitPlayer.isAlive = false;
          shooter.kills += 1;
          this.endMatch(shooter.id);
        }
      }
    }
  }

  onLeave(client: Client, consented: boolean) {
    console.log(`${client.sessionId} left game`);
    this.state.players.delete(client.sessionId);
    
    // End match if someone leaves
    this.endMatch(null);
  }

  private startGame() {
    console.log('Match started!');
    this.state.status = 'active';
    this.matchStartTime = Date.now();

    // Game loop to update game time
    this.gameLoop = setInterval(() => {
      this.state.gameTime = (Date.now() - this.matchStartTime) / 1000;
      
      // Max game time: 5 minutes
      if (this.state.gameTime > 300) {
        this.endMatch(null);
      }
    }, 100);
  }

  private endMatch(winnerId: string | null) {
    this.state.status = 'ended';
    if (this.gameLoop) clearInterval(this.gameLoop);

    const winner = winnerId ? this.state.players.get(winnerId) : null;
    const message = {
      winnerId,
      winnerUsername: winner?.username || 'Draw',
      gameTime: this.state.gameTime,
      stats: Array.from(this.state.players.values()).map((p) => ({
        username: p.username,
        kills: p.kills,
      })),
    };

    // Broadcast to all clients
    this.broadcast('match_ended', message);

    // Dispose room after 2 seconds
    setTimeout(() => this.dispose(), 2000);
  }

  onDispose() {
    if (this.gameLoop) clearInterval(this.gameLoop);
    console.log('Game room disposed');
  }
}
