import { createStore } from 'vuex';
import { StorageService } from '../services/StorageService';
import { parseTime, formatTime } from '../utils/timeFormatter';

const MAX_NEGATIVE_SECONDS = -(59 * 60 + 59); // -59:59
const DEFAULT_AVATAR_MARKER = null; // Ensure this is defined

// Define predefined players
const predefinedPlayers = [
  {
    id: 'predefined-1', // Unique ID for predefined player 1
    name: 'Player 1',
    avatar: DEFAULT_AVATAR_MARKER, // Or a specific avatar path if you have one
    initialTimerSec: 60 * 60, // 60:00
    currentTimerSec: 60 * 60,
    hotkey: '1', // Hotkey '1'
    isSkipped: false,
    isTimerRunning: false,
  },
  {
    id: 'predefined-2', // Unique ID for predefined player 2
    name: 'Player 2',
    avatar: DEFAULT_AVATAR_MARKER, // Or a specific avatar path
    initialTimerSec: 60 * 60, // 60:00
    currentTimerSec: 60 * 60,
    hotkey: '2', // Hotkey '2'
    isSkipped: false,
    isTimerRunning: false,
  }
];

const initialState = {
  players: JSON.parse(JSON.stringify(predefinedPlayers)), // Start with predefined players (deep copy)
  globalHotkeyStopPause: null,
  globalHotkeyRunAll: null,
  globalHotkeyPassTurn: null,
  globalMqttStopPause: null,
  globalMqttRunAll: null,
  globalMqttPassTurn: null,
  mqttBrokerUrl: 'ws://localhost:9001',
  mqttConnectDesired: false,
  currentPlayerIndex: 0,
  gameMode: 'normal',
  isMuted: false,
  theme: 'dark',
  gameRunning: false,
};

// Helper function to create a new player object
const createPlayerObject = (playerData = {}) => ({
  id: playerData.id || Date.now().toString() + Math.random(),
  name: playerData.name || `Player ${store.state.players.length + 1}`, // Access store carefully here or pass length
  avatar: playerData.avatar === undefined ? DEFAULT_AVATAR_MARKER : playerData.avatar,
  initialTimerSec: playerData.initialTimerSec || 3600,
  currentTimerSec: playerData.currentTimerSec || playerData.initialTimerSec || 3600,
  hotkey: playerData.hotkey || null,
  mqttChar: playerData.mqttChar || null, // New
  isSkipped: playerData.isSkipped || false,
  isTimerRunning: playerData.isTimerRunning || false,
});

export default createStore({
  state: () => {
    const persistedState = StorageService.getState();
    if (persistedState) {
      let playersToUse = persistedState.players;
      if (!playersToUse || (playersToUse.length === 0 && !persistedState.hasOwnProperty('players'))) {
        playersToUse = JSON.parse(JSON.stringify(predefinedPlayers.map(p => createPlayerObject(p))));
      } else if (persistedState.hasOwnProperty('players') && playersToUse.length === 0) {
        playersToUse = [];
      }

      playersToUse = playersToUse.map(p_persisted => {
        const p_base = predefinedPlayers.find(p_def => p_def.id === p_persisted.id) || {};
        return createPlayerObject({ ...p_base, ...p_persisted, isTimerRunning: false });
      });
      
      return {
        ...initialState, // Start with all initial state defaults
        ...persistedState, // Override with persisted values
        players: playersToUse, // Specifically set processed players
        globalHotkeyPassTurn: persistedState.globalHotkeyPassTurn || initialState.globalHotkeyPassTurn,
        globalMqttPassTurn: persistedState.globalMqttPassTurn || initialState.globalMqttPassTurn,
        globalHotkeyStopPause: persistedState.globalHotkeyStopPause || initialState.globalHotkeyStopPause,
        globalMqttStopPause: persistedState.globalMqttStopPause || initialState.globalMqttStopPause,
        globalHotkeyRunAll: persistedState.globalHotkeyRunAll || initialState.globalHotkeyRunAll,
        globalMqttRunAll: persistedState.globalMqttRunAll || initialState.globalMqttRunAll,
        mqttBrokerUrl: persistedState.mqttBrokerUrl || initialState.mqttBrokerUrl,
        mqttConnectDesired: persistedState.hasOwnProperty('mqttConnectDesired') ? persistedState.mqttConnectDesired : initialState.mqttConnectDesired,
        gameRunning: false, // Always start non-running
        currentPlayerIndex: persistedState.currentPlayerIndex !== undefined && persistedState.currentPlayerIndex < playersToUse.length ? persistedState.currentPlayerIndex : 0,
      };
    }
    // If no persisted state, deep copy initialState which includes new MQTT fields
    const newInitialState = JSON.parse(JSON.stringify(initialState));
    newInitialState.players = newInitialState.players.map(p => createPlayerObject(p));
    return newInitialState;
  },
  mutations: {
    ADD_PLAYER(state, playerConfig) {
      if (state.players.length < 99) {
        const newPlayer = createPlayerObject({
            name: playerConfig.name,
            avatar: playerConfig.avatar,
            initialTimerSec: playerConfig.initialTimerSec,
            currentTimerSec: playerConfig.currentTimerSec, // Set from form
            hotkey: playerConfig.hotkey,
            mqttChar: playerConfig.mqttChar // From form
        });
        state.players.push(newPlayer);
      } else {
        alert("Maximum player limit (99) reached.");
      }
    },
    UPDATE_PLAYER(state, updatedPlayer) {
      const index = state.players.findIndex(p => p.id === updatedPlayer.id);
      if (index !== -1) {
        state.players[index] = { ...state.players[index], ...updatedPlayer };
      }
    },
    SET_MQTT_BROKER_URL(state, url) {
      state.mqttBrokerUrl = url;
      state.mqttConnectDesired = true; 
    },
    SET_MQTT_CONNECT_DESIRED(state, desired) {
      state.mqttConnectDesired = desired;
    },
    SET_GLOBAL_HOTKEY_STOP_PAUSE(state, key) {
      state.globalHotkeyStopPause = key;
    },
    SET_GLOBAL_HOTKEY_RUN_ALL(state, key) {
      state.globalHotkeyRunAll = key;
    },
    SET_GLOBAL_HOTKEY_PASS_TURN(state, key) {
      state.globalHotkeyPassTurn = key;
    },
    SET_GLOBAL_MQTT_PASS_TURN(state, char) { 
      state.globalMqttPassTurn = char;
    },
    SET_GLOBAL_MQTT_STOP_PAUSE(state, char) {
      state.globalMqttStopPause = char;
    },
    SET_GLOBAL_MQTT_RUN_ALL(state, char) {
      state.globalMqttRunAll = char;
    },
    SET_PLAYERS(state, playersData) { // Used by fullResetApp and potentially reorder
      state.players = playersData.map(p => createPlayerObject(p));
    },
    SET_THEME(state, theme) { state.theme = theme; },
    DELETE_PLAYER(state, playerId) {
      state.players = state.players.filter(p => p.id !== playerId);
      if (state.currentPlayerIndex >= state.players.length && state.players.length > 0) {
        state.currentPlayerIndex = state.players.length - 1;
      } else if (state.players.length === 0) {
        state.currentPlayerIndex = 0;
      }
    },
    REORDER_PLAYERS(state, players) {
        state.players = players;
    },
    SHUFFLE_PLAYERS(state) {
        for (let i = state.players.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [state.players[i], state.players[j]] = [state.players[j], state.players[i]];
        }
    },
    REVERSE_PLAYERS(state) {
        state.players.reverse();
    },
    SET_CURRENT_PLAYER_INDEX(state, index) {
      state.currentPlayerIndex = index;
    },
    SET_GAME_MODE(state, mode) {
      state.gameMode = mode;
    },
    SET_IS_MUTED(state, muted) {
      state.isMuted = muted;
    },
    TOGGLE_THEME(state) {
      state.theme = state.theme === 'light' ? 'dark' : 'light';
    },
    SET_THEME(state, theme) {
      state.theme = theme;
    },
    DECREMENT_TIMER(state, { playerIndex }) {
      const player = state.players[playerIndex];
      if (player && player.isTimerRunning && !player.isSkipped) {
        player.currentTimerSec--;
        if (player.currentTimerSec < MAX_NEGATIVE_SECONDS) {
          player.currentTimerSec = MAX_NEGATIVE_SECONDS;
          player.isSkipped = true; // Auto-skip if max negative time reached
          player.isTimerRunning = false;
        }
      }
    },
    RESET_PLAYER_TIMER(state, playerIndex) {
        if (state.players[playerIndex]) {
            state.players[playerIndex].currentTimerSec = state.players[playerIndex].initialTimerSec;
            state.players[playerIndex].isSkipped = false;
            state.players[playerIndex].isTimerRunning = false;
        }
    },
    RESET_ALL_TIMERS(state) {
      // When resetting, decide if you want to go back to *only* predefined players
      // or reset existing players' timers. The current spec "restores all timers to initial values"
      // implies resetting existing players. If it meant reverting to the initial player set,
      // this logic would need to change to:
      // state.players = JSON.parse(JSON.stringify(predefinedPlayers));
      // For now, sticking to resetting current players' timers:
      state.players.forEach(player => {
        player.currentTimerSec = player.initialTimerSec;
        player.isSkipped = false;
        player.isTimerRunning = false;
      });
      state.currentPlayerIndex = 0;
      state.gameMode = 'normal';
      state.gameRunning = false;
    },
    START_PLAYER_TIMER(state, playerIndex) {
        if(state.players[playerIndex] && !state.players[playerIndex].isSkipped) {
            state.players[playerIndex].isTimerRunning = true;
            state.gameRunning = true;
        }
    },
    PAUSE_PLAYER_TIMER(state, playerIndex) {
        if(state.players[playerIndex]) {
            state.players[playerIndex].isTimerRunning = false;
        }
        if (!state.players.some(p => p.isTimerRunning)) {
            state.gameRunning = false;
        }
    },
    PAUSE_ALL_TIMERS(state) {
        state.players.forEach(p => p.isTimerRunning = false);
        state.gameRunning = false;
    },
    SET_GAME_RUNNING(state, isRunning) {
        state.gameRunning = isRunning;
    },
  },
  actions: {
    loadState({ commit, state }) {
      // The state initializer already did the main loading from localStorage.
      // This action can be used for any *additional* setup after initial hydration
      // or to re-apply certain defaults if needed.
      // For now, it's mainly a confirmation that persisted state is used.

      // Example: ensure theme is applied if it was loaded
      // This is already handled by App.vue's watcher, but could be centralized.
      // if (state.theme === 'dark') {
      //   document.documentElement.classList.add('dark');
      // } else {
      //   document.documentElement.classList.remove('dark');
      // }
      console.log("Store state loaded/initialized.");
      // It's good practice for actions to return a Promise if they are async
      // or if other parts of the app expect to chain .then()
      return Promise.resolve(); // Resolve immediately
    },
    saveState({ state }) {
      StorageService.saveState({
        players: state.players.map(p => ({ // Persist mqttChar for players
            id: p.id, name: p.name, avatar: p.avatar, 
            initialTimerSec: p.initialTimerSec, currentTimerSec: p.currentTimerSec,
            hotkey: p.hotkey, mqttChar: p.mqttChar, // Save mqttChar
            isSkipped: p.isSkipped,
        })),
        globalHotkeyPassTurn: state.globalHotkeyPassTurn,
        globalMqttPassTurn: state.globalMqttPassTurn,
        globalHotkeyStopPause: state.globalHotkeyStopPause,
        globalHotkeyRunAll: state.globalHotkeyRunAll,
        globalMqttStopPause: state.globalMqttStopPause, 
        globalMqttRunAll: state.globalMqttRunAll,       
        mqttBrokerUrl: state.mqttBrokerUrl,             
        mqttConnectDesired: state.mqttConnectDesired,
        currentPlayerIndex: state.currentPlayerIndex,
        gameMode: state.gameMode,
        isMuted: state.isMuted,
        theme: state.theme,
      });
    },
    addPlayer({ commit, dispatch }, player) {
      commit('ADD_PLAYER', player);
      dispatch('saveState');
    },
    setMqttBrokerUrl({ commit, dispatch }, url) {
      commit('SET_MQTT_BROKER_URL', url);
      dispatch('saveState');
    },
    setMqttConnectDesired({ commit, dispatch }, desired) {
      commit('SET_MQTT_CONNECT_DESIRED', desired);
      dispatch('saveState');
    },
    setGlobalMqttStopPause({ commit, dispatch }, char) {
      commit('SET_GLOBAL_MQTT_STOP_PAUSE', char);
      dispatch('saveState');
    },
    setGlobalMqttRunAll({ commit, dispatch }, char) {
      commit('SET_GLOBAL_MQTT_RUN_ALL', char);
      dispatch('saveState');
    },
    setGlobalHotkeyPassTurn({ commit, dispatch }, key) {
        commit('SET_GLOBAL_HOTKEY_PASS_TURN', key);
        dispatch('saveState');
    },
    setGlobalMqttPassTurn({ commit, dispatch }, char) {
        commit('SET_GLOBAL_MQTT_PASS_TURN', char);
        dispatch('saveState');
    },
    updatePlayer({ commit, dispatch }, player) {
      commit('UPDATE_PLAYER', player);
      dispatch('saveState');
    },
    deletePlayer({ commit, dispatch }, playerId) {
      commit('DELETE_PLAYER', playerId);
      dispatch('saveState');
    },
    reorderPlayers({commit, dispatch}, players) {
      commit('REORDER_PLAYERS', players);
      dispatch('saveState');
    },
    shufflePlayers({commit, dispatch}) {
        commit('SHUFFLE_PLAYERS');
        dispatch('saveState');
    },
    reversePlayers({commit, dispatch}) {
        commit('REVERSE_PLAYERS');
        dispatch('saveState');
    },
    toggleTheme({ commit, dispatch }) {
      commit('TOGGLE_THEME');
      dispatch('saveState');
    },
    setGlobalHotkey({ commit, dispatch }, key) {
      commit('SET_GLOBAL_HOTKEY_STOP_PAUSE', key);
      dispatch('saveState');
    },
    setMuted({ commit, dispatch }, muted) {
      commit('SET_IS_MUTED', muted);
      dispatch('saveState');
    },
    resetGame({ commit, dispatch }) {
        commit('RESET_ALL_TIMERS');
        dispatch('saveState');
    },
    setGlobalHotkeyStopPause({ commit, dispatch }, key) {
      commit('SET_GLOBAL_HOTKEY_STOP_PAUSE', key);
      dispatch('saveState');
    },
    setGlobalHotkeyRunAll({ commit, dispatch }, key) {
        commit('SET_GLOBAL_HOTKEY_RUN_ALL', key);
        dispatch('saveState');
    },
    fullResetApp({ commit, dispatch, state: currentGlobalState }) {
        StorageService.clearState();
        const freshInitialState = JSON.parse(JSON.stringify(initialState));
        freshInitialState.players = freshInitialState.players.map(p => createPlayerObject(p));

        commit('SET_PLAYERS', freshInitialState.players);
        commit('SET_CURRENT_PLAYER_INDEX', freshInitialState.currentPlayerIndex);
        commit('SET_GAME_MODE', freshInitialState.gameMode);
        commit('SET_IS_MUTED', freshInitialState.isMuted);
        commit('SET_MQTT_BROKER_URL', freshInitialState.mqttBrokerUrl);
        commit('SET_MQTT_CONNECT_DESIRED', freshInitialState.mqttConnectDesired);
        commit('SET_GLOBAL_HOTKEY_STOP_PAUSE', freshInitialState.globalHotkeyStopPause);
        commit('SET_GLOBAL_MQTT_STOP_PAUSE', freshInitialState.globalMqttStopPause);
        commit('SET_GLOBAL_HOTKEY_RUN_ALL', freshInitialState.globalHotkeyRunAll);
        commit('SET_GLOBAL_MQTT_RUN_ALL', freshInitialState.globalMqttRunAll);
        commit('SET_GLOBAL_HOTKEY_PASS_TURN', freshInitialState.globalHotkeyPassTurn);
        commit('SET_GLOBAL_MQTT_PASS_TURN', freshInitialState.globalMqttPassTurn);
        
        if (currentGlobalState.theme !== freshInitialState.theme) {
             commit('SET_THEME', freshInitialState.theme);
        }
        commit('SET_GAME_RUNNING', false);
        dispatch('saveState');
    },
    tick({ commit, state }) {
      if (state.gameMode === 'normal') {
        if (state.players[state.currentPlayerIndex]?.isTimerRunning) {
          commit('DECREMENT_TIMER', { playerIndex: state.currentPlayerIndex });
        }
      } else if (state.gameMode === 'allTimers') {
        state.players.forEach((player, index) => {
          if (player.isTimerRunning) {
            commit('DECREMENT_TIMER', { playerIndex: index });
          }
        });
      }
    },
    passTurn({ commit, state, dispatch }) {
        const numPlayers = state.players.length;
        if (numPlayers === 0) return;

        const currentIdx = state.currentPlayerIndex;
        const currentPlayerTimerWasRunning = state.players[currentIdx]?.isTimerRunning;

        commit('PAUSE_PLAYER_TIMER', currentIdx);

        let nextPlayerIndex = (currentIdx + 1) % numPlayers;
        let skippedCount = 0;
        while(state.players[nextPlayerIndex]?.isSkipped && skippedCount < numPlayers) {
            nextPlayerIndex = (nextPlayerIndex + 1) % numPlayers;
            skippedCount++;
        }

        if (skippedCount === numPlayers) {
            commit('PAUSE_ALL_TIMERS');
            dispatch('saveState');
            return;
        }
        
        commit('SET_CURRENT_PLAYER_INDEX', nextPlayerIndex);

        if (currentPlayerTimerWasRunning && !state.players[nextPlayerIndex].isSkipped) {
            commit('START_PLAYER_TIMER', nextPlayerIndex);
        } else {
            if (state.players[nextPlayerIndex] && !state.players[nextPlayerIndex].isSkipped) {
                 commit('PAUSE_PLAYER_TIMER', nextPlayerIndex);
            }
        }
        
        dispatch('saveState');
    },
    toggleCurrentPlayerTimerNormalMode({ commit, state, dispatch }) {
        const player = state.players[state.currentPlayerIndex];
        if (!player) return;

        if (player.isTimerRunning) {
            commit('PAUSE_PLAYER_TIMER', state.currentPlayerIndex);
        } else if (!player.isSkipped) {
            commit('START_PLAYER_TIMER', state.currentPlayerIndex);
        }
        dispatch('saveState');
    },
    togglePlayerTimerAllTimersMode({ commit, state, dispatch }, playerIndex) {
        const player = state.players[playerIndex];
        if (!player) return;

        if (player.isTimerRunning) {
            commit('PAUSE_PLAYER_TIMER', playerIndex);
        } else if (!player.isSkipped) {
            commit('START_PLAYER_TIMER', playerIndex);
        }
        
        const anyTimerRunning = state.players.some(p => p.isTimerRunning && !p.isSkipped);
        if (!anyTimerRunning && state.players.length > 0 && state.gameMode === 'allTimers') {
            // This auto-revert logic is now in GameView.vue watcher for better control over timing
        }
        dispatch('saveState');
    },
    globalStopPauseAll({ commit, state, dispatch }) {
        if (state.gameMode === 'normal') {
            dispatch('toggleCurrentPlayerTimerNormalMode');
        } else { 
            const anyTimerRunning = state.players.some(p => p.isTimerRunning && !p.isSkipped);
            if (anyTimerRunning) { 
                commit('PAUSE_ALL_TIMERS');
            } else { 
                state.players.forEach((player, index) => {
                    if (!player.isSkipped) {
                        commit('START_PLAYER_TIMER', index);
                    }
                });
            }
        }
        dispatch('saveState');
    },
    switchToAllTimersMode({ commit, state, dispatch }) {
        commit('SET_GAME_MODE', 'allTimers');
        let anyStarted = false;
        state.players.forEach((player, index) => {
            if (!player.isSkipped) {
                commit('START_PLAYER_TIMER', index);
                anyStarted = true;
            }
        });
        if(anyStarted) commit('SET_GAME_RUNNING', true);
        else commit('SET_GAME_RUNNING', false);
        dispatch('saveState');
    },
    switchToNormalMode({commit, state, dispatch}) {
        commit('PAUSE_ALL_TIMERS');
        commit('SET_GAME_MODE', 'normal');
        // Determine current player for normal mode, respecting skips
        let currentIdx = state.currentPlayerIndex;
        let skippedCount = 0;
        while(state.players[currentIdx]?.isSkipped && skippedCount < state.players.length) {
            currentIdx = (currentIdx + 1) % state.players.length;
            skippedCount++;
        }
        if (skippedCount < state.players.length) {
             commit('SET_CURRENT_PLAYER_INDEX', currentIdx);
             // Timer for this player should remain paused as per PAUSE_ALL_TIMERS
        } else {
            // All players skipped, game is effectively paused.
            commit('SET_GAME_RUNNING', false);
        }
        dispatch('saveState');
    }
  },
  getters: {
    players: state => state.players,
    currentPlayer: state => state.players[state.currentPlayerIndex],
    nextPlayer: state => {
      if (!state.players || state.players.length < 1) return null;
      let nextIndex = (state.currentPlayerIndex + 1) % state.players.length;
      let count = 0;
      while(state.players[nextIndex]?.isSkipped && count < state.players.length) {
        nextIndex = (nextIndex + 1) % state.players.length;
        count++;
      }
      return state.players[nextIndex];
    },
    getPlayerById: (state) => (id) => state.players.find(p => p.id === id),
    gameMode: state => state.gameMode,
    isMuted: state => state.isMuted,
    theme: state => state.theme,
    mqttBrokerUrl: state => state.mqttBrokerUrl,
    mqttConnectDesired: state => state.mqttConnectDesired,
    globalHotkeyStopPause: state => state.globalHotkeyStopPause,
    globalMqttStopPause: state => state.globalMqttStopPause,
    globalHotkeyRunAll: state => state.globalHotkeyRunAll,
    globalMqttRunAll: state => state.globalMqttRunAll,
    globalHotkeyPassTurn: state => state.globalHotkeyPassTurn,
    globalMqttPassTurn: state => state.globalMqttPassTurn,    
    totalPlayers: state => state.players.length,
    gameRunning: state => state.gameRunning,
    maxNegativeTimeReached: () => MAX_NEGATIVE_SECONDS,
  }
});