const roomController = require('./room');
const youtubeService = require('../services/youtubeService');

const shuffleArray = (array) => {
  const shuffled = [...array];
  for (let i = shuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
  }
  return shuffled;
};

const gameStates = {};

const initializeGameState = (roomId) => {
    if (!gameStates[roomId]) {
        gameStates[roomId] = {
            round: 0,
            phase: 'waiting',
            roles: {},
            selectedSong: null,
            scores: {},
            songOptions: [],
            guessResults: {},
            currentComposer: null,
            roundStartTime: null,
            phaseTimeLimit: {
                composing: 30,
                guessing: 10
            },
            lastFrequency: 440,
        };

        const users = roomController.getRoomUsers(roomId);
        users.forEach(user => {
            gameStates[roomId].scores[user.id] = 0;
        });
    }

    return gameStates[roomId];
};

const startNewRound = async (roomId) => {
    const gameState = gameStates[roomId];
    if (!gameState) return false;

    const users = roomController.getRoomUsers(roomId);
    if (users.length < 2) return false;

    gameState.round += 1;
    gameState.phase = 'composing';
    gameState.guessResults = {};
    gameState.roundStartTime = Date.now();
    gameState.roles = {};

    gameState.currentComposer = determineNextComposer(roomId, gameState, users);

    const success = await selectSongAndOptions(gameState);
    if (!success) return false;

    users.forEach(user => {
        gameState.roles[user.id] = user.id === gameState.currentComposer ? 'composer' : 'guesser';
    });

    return true;
};

const determineNextComposer = (roomId, gameState, users) => {
    if (gameState.round === 1 || !gameState.currentComposer) {
        return users[Math.floor(Math.random() * users.length)].id;
    }

    const currentIndex = users.findIndex(user => user.id === gameState.currentComposer);

    if (currentIndex === -1) {
        return users[Math.floor(Math.random() * users.length)].id;
    }

    return users[(currentIndex + 1) % users.length].id;
};

// Then modify the selectSongAndOptions function to use the shuffle:
const selectSongAndOptions = async (gameState) => {
  try {
    const availableIds = await youtubeService.getAvailableSongIds();
    
    if (!availableIds || availableIds.length === 0) {
      console.error("No song IDs available for selection");
      return false;
    }

    const selectedId = availableIds[Math.floor(Math.random() * availableIds.length)];
    gameState.selectedSong = { id: selectedId };

    const optionIds = new Set([selectedId]);
    const attempts = Math.min(20, availableIds.length);

    let count = 0;
    while (optionIds.size < 5 && count < attempts) {
      const randomId = availableIds[Math.floor(Math.random() * availableIds.length)];
      optionIds.add(randomId);
      count++;
    }

    // Shuffle the song options to randomize the position of the correct answer
    gameState.songOptions = shuffleArray(Array.from(optionIds).map(id => ({ id })));
    
    return true;
  } catch (error) {
    console.error("Error selecting songs and options:", error);
    return false;
  }
};

const getTimeRemaining = (roomId) => {
    const gameState = gameStates[roomId];
    if (!gameState || !gameState.roundStartTime) return 0;

    const phaseDuration = gameState.phaseTimeLimit[gameState.phase] * 1000;
    const timeElapsed = Date.now() - gameState.roundStartTime;
    const timeRemaining = Math.max(0, phaseDuration - timeElapsed);

    return Math.ceil(timeRemaining / 1000);
};

const advancePhase = (roomId) => {
    const gameState = gameStates[roomId];
    if (!gameState) {
        console.error(`Cannot advance phase: no game state for room ${roomId}`);
        return false;
    }
    
    const currentPhase = gameState.phase;
    console.log(`Advancing phase for room ${roomId} from ${currentPhase}`);
    
    if (currentPhase === 'composing') {
        gameState.phase = 'guessing';
        gameState.roundStartTime = Date.now();
        console.log(`Room ${roomId} advanced to guessing phase`);
        return { phase: 'guessing' };
    } 
    else if (currentPhase === 'guessing') {
        gameState.phase = 'results';
        console.log(`Room ${roomId} advanced to results phase`);
        return { phase: 'results' };
    } 
    else if (currentPhase === 'results') {
        console.log(`Room ${roomId} starting new round from results phase`);
        return startNewRound(roomId);
    }
    
    console.warn(`Cannot advance from unknown phase "${currentPhase}" in room ${roomId}`);
    return false;
};

const updateFrequency = (roomId, frequency) => {
    if (!gameStates[roomId]) return false;
    gameStates[roomId].lastFrequency = frequency;
    return true;
};

const submitGuess = (roomId, userId, songId) => {
    const gameState = gameStates[roomId];
    if (!gameState || gameState.phase !== 'guessing' || gameState.roles[userId] !== 'guesser') {
        return false;
    }

    const isCorrect = gameState.selectedSong.id === parseInt(songId);
    const points = isCorrect ? 10 : 0;

    gameState.guessResults[userId] = {songId, isCorrect, points};

    if (isCorrect) {
        gameState.scores[userId] = (gameState.scores[userId] || 0) + points;
    }

    return {
        isCorrect,
        correctSong: gameState.selectedSong,
        points
    };
};

const getCurrentFrequency = (roomId) => gameStates[roomId]?.lastFrequency || 440;
const getRoles = (roomId) => gameStates[roomId]?.roles || {};
const getUserRole = (roomId, userId) => gameStates[roomId]?.roles[userId] || null;
const getSongOptions = (roomId) => gameStates[roomId]?.songOptions || [];
const getSelectedSong = (roomId) => gameStates[roomId]?.selectedSong || null;
const getRoundResults = (roomId) => {
    const gameState = gameStates[roomId];
    if (!gameState) return {round: 0, scores: {}, guessResults: {}, selectedSong: null};

    const playerNames = {};
    Object.keys(gameState.scores).forEach(userId => {
        playerNames[userId] = roomController.getUserName(userId) || "Player";
    });

    return {
        round: gameState.round,
        selectedSong: gameState.selectedSong,
        guessResults: gameState.guessResults,
        scores: gameState.scores,
        playerNames: playerNames
    };
};

const cleanupGameState = (roomId) => {
    delete gameStates[roomId];
};

const getCurrentComposer = (roomId) => gameStates[roomId]?.currentComposer || null;

const getGameState = (roomId) => {
    return gameStates[roomId] || null;
};

module.exports = {
    initializeGameState,
    startNewRound,
    getTimeRemaining,
    advancePhase,
    updateFrequency,
    getCurrentFrequency,
    submitGuess,
    getRoundResults,
    getRoles,
    getUserRole,
    getSongOptions,
    getSelectedSong,
    cleanupGameState,
    getCurrentComposer,
    getGameState
};