import { createStore } from 'vuex';
import dialogs from './modules/dialogs';
import loadMenu from '../utils/menuLoader.js';
import router from '../router';
import apiClient from '../utils/axios.js';
import { io } from 'socket.io-client';

const store = createStore({
  state: {
    isLoggedIn: localStorage.getItem('isLoggedIn') === 'true',
    connectionStatus: 'disconnected', // 'connected', 'connecting', 'disconnected', 'error'
    user: JSON.parse(localStorage.getItem('user')) || null,
    language: (() => {
      // Verwende die gleiche Logik wie in main.js
      const browserLanguage = navigator.language || navigator.languages[0];
      const germanSpeakingCountries = ['de', 'at', 'ch', 'li'];
      
      if (browserLanguage.startsWith('de')) {
        return 'de';
      }
      
      const allLanguages = navigator.languages || [navigator.language];
      for (const lang of allLanguages) {
        if (lang.startsWith('de-')) {
          const countryCode = lang.split('-')[1]?.toLowerCase();
          if (germanSpeakingCountries.includes(countryCode)) {
            return 'de';
          }
        }
        if (lang.startsWith('de_')) {
          const countryCode = lang.split('_')[1]?.toLowerCase();
          if (germanSpeakingCountries.includes(countryCode)) {
            return 'de';
          }
        }
      }
      
      return 'en';
    })(),
    menu: JSON.parse(localStorage.getItem('menu')) || [],
    socket: null,
    daemonSocket: null,
    menuNeedsUpdate: false,
  },
  mutations: {
    async dologin(state, user) {
      state.isLoggedIn = true;
      state.user = user;
      localStorage.setItem('isLoggedIn', 'true');
      localStorage.setItem('user', JSON.stringify(user));
      state.menuNeedsUpdate = true;
      if (user.param.filter(param => ['birthdate', 'gender'].includes(param.name)).length < 2) {
        router.push({ path: '/settings/personal' });
      }
    },
    async dologout(state) {
      state.isLoggedIn = false;
      state.user = null;
      localStorage.removeItem('isLoggedIn');
      localStorage.removeItem('user');
      localStorage.removeItem('menu');
      state.menuNeedsUpdate = false;
      
      // Setze die Sprache auf die Browser-Sprache zurück
      const browserLanguage = navigator.language || navigator.languages[0];
      const germanSpeakingCountries = ['de', 'at', 'ch', 'li'];
      
      if (browserLanguage.startsWith('de')) {
        state.language = 'de';
      } else {
        const allLanguages = navigator.languages || [navigator.language];
        let isGerman = false;
        for (const lang of allLanguages) {
          if (lang.startsWith('de-')) {
            const countryCode = lang.split('-')[1]?.toLowerCase();
            if (germanSpeakingCountries.includes(countryCode)) {
              isGerman = true;
              break;
            }
          }
          if (lang.startsWith('de_')) {
            const countryCode = lang.split('_')[1]?.toLowerCase();
            if (germanSpeakingCountries.includes(countryCode)) {
              isGerman = true;
              break;
            }
          }
        }
        state.language = isGerman ? 'de' : 'en';
      }
    },
    setLanguage(state, language) {
      state.language = language;
    },
    setMenu(state, menu) {
      state.menu = menu;
      localStorage.setItem('menu', JSON.stringify(menu));
      state.menuNeedsUpdate = false;
    },
    setSocket(state, socket) {
      state.socket = socket;
    },
    setConnectionStatus(state, status) {
      state.connectionStatus = status;
    },
    clearSocket(state) {
      if (state.socket) {
        state.socket.disconnect();
      }
      state.socket = null;
    },
    setDaemonSocket(state, daemonSocket) {
      state.daemonSocket = daemonSocket;
    },
    clearDaemonSocket(state) {
      if (state.daemonSocket) {
        state.daemonSocket.close();
      }
      state.daemonSocket = null;
    },
  },
  actions: {
    async login({ commit, dispatch }, user) {
      await commit('dologin', user);
      await dispatch('initializeSocket');
      await dispatch('initializeDaemonSocket');
      const socket = this.getters.socket;
      if (socket) {
        const idForSocket = user?.hashedId || user?.id;
        if (idForSocket) socket.emit('setUserId', idForSocket);
      }
      await dispatch('loadMenu');
    },
    logout({ commit }) {
      commit('clearSocket');
      commit('clearDaemonSocket');
      commit('dologout');
      router.push('/');
    },
    initializeSocket({ commit, state }) {
      if (state.isLoggedIn && state.user) {
        let currentSocket = state.socket;
        const connectSocket = () => {
          if (currentSocket) {
            currentSocket.disconnect();
          }
          commit('setConnectionStatus', 'connecting');
          const socketIoUrl = import.meta.env.VITE_SOCKET_IO_URL || import.meta.env.VITE_API_BASE_URL;
          console.log('🔌 Initializing Socket.io connection to:', socketIoUrl);
          const socket = io(socketIoUrl, {
            secure: true,
            transports: ['websocket', 'polling']
          });
          
          socket.on('connect', () => {
            console.log('✅ Socket.io connected successfully');
            retryCount = 0; // Reset retry counter on successful connection
            commit('setConnectionStatus', 'connected');
            const idForSocket = state.user?.hashedId || state.user?.id;
            if (idForSocket) socket.emit('setUserId', idForSocket);
          });

          socket.on('disconnect', (reason) => {
            console.warn('❌ Socket.io disconnected:', reason);
            commit('setConnectionStatus', 'disconnected');
            retryConnection(connectSocket);
          });

          socket.on('connect_error', (error) => {
            console.error('❌ Socket.io connection error:', error);
            console.error('❌ URL attempted:', import.meta.env.VITE_API_BASE_URL);
            commit('setConnectionStatus', 'error');
          });
    
          commit('setSocket', socket);
        };
    
        let retryCount = 0;
        const maxRetries = 10;
        const retryConnection = (reconnectFn) => {
          if (retryCount >= maxRetries) {
            console.error('❌ Max retry attempts reached for Socket.io');
            return;
          }
          retryCount++;
          const delay = Math.min(1000 * Math.pow(1.5, retryCount - 1), 30000); // Exponential backoff, max 30s
          console.log(`🔄 Retrying Socket.io connection in ${delay}ms (attempt ${retryCount}/${maxRetries})`);
          setTimeout(() => {
            reconnectFn();
          }, delay);
        };
    
        connectSocket();
      } else {
        console.log("User is not logged in or user data is not available.");
      }
    },
    initializeDaemonSocket({ commit, state }) {
      if (!state.isLoggedIn || !state.user) {
        console.log("User is not logged in or user data is not available for Daemon WebSocket.");
        return;
      }

      const daemonUrl = import.meta.env.VITE_DAEMON_SOCKET || 'wss://www.your-part.de:4551';
      console.log('🔌 Initializing Daemon WebSocket connection to:', daemonUrl);
      
      const connectDaemonSocket = () => {
        // Protokoll-Fallback: zuerst mit Subprotokoll, dann ohne
        const protocols = ['yourpart-protocol', undefined];
        let attemptIndex = 0;

        const tryConnectWithProtocol = () => {
          const currentProtocol = protocols[attemptIndex];
          try {
            const daemonSocket = currentProtocol
              ? new WebSocket(daemonUrl, currentProtocol)
              : new WebSocket(daemonUrl);
            console.log('🔌 Protocol:', currentProtocol ?? 'none (fallback)');

            let opened = false;

            daemonSocket.onopen = () => {
              opened = true;
              console.log('✅ Daemon WebSocket connected successfully');
              retryCount = 0; // Reset retry counter on successful connection
              const payload = JSON.stringify({
                user_id: state.user.id,
                event: 'setUserId',
                data: { userId: state.user.id }
              });
              daemonSocket.send(payload);
            };

            daemonSocket.onclose = (event) => {
              console.warn('❌ Daemon WebSocket disconnected:', event.reason);
              console.warn('❌ Close details:', {
                code: event.code,
                reason: event.reason,
                wasClean: event.wasClean,
                readyState: daemonSocket.readyState
              });
              // Falls Verbindungsaufbau nicht offen war und es noch einen Fallback gibt → nächsten Versuch ohne Subprotokoll
              if (!opened && attemptIndex < protocols.length - 1) {
                attemptIndex += 1;
                console.warn('🔄 Fallback: versuche erneut ohne Subprotokoll...');
                tryConnectWithProtocol();
                return;
              }
              retryConnection(connectDaemonSocket);
            };

            daemonSocket.onerror = (error) => {
              console.error('❌ Daemon WebSocket error:', error);
              console.error('❌ Error details:', {
                type: error.type,
                target: error.target,
                readyState: daemonSocket.readyState,
                url: daemonSocket.url,
                protocol: daemonSocket.protocol
              });
              console.error('❌ Browser info:', {
                userAgent: navigator.userAgent,
                location: window.location.href,
                isSecure: window.location.protocol === 'https:'
              });
              // Bei Fehler vor Open: Fallback versuchen
              if (!opened && attemptIndex < protocols.length - 1) {
                attemptIndex += 1;
                console.warn('🔄 Fallback: versuche erneut ohne Subprotokoll (onerror)...');
                tryConnectWithProtocol();
                return;
              }
              retryConnection(connectDaemonSocket);
            };

            daemonSocket.addEventListener('message', (event) => {
              const message = event.data;
              if (message === "ping") {
                daemonSocket.send("pong");
              } else {
                try {
                  const data = JSON.parse(message);
                  // Handle daemon messages here
                  console.log('📨 Daemon message received:', data);
                } catch (error) {
                  console.error("Error parsing daemon message:", error);
                }
              }
            });

            commit('setDaemonSocket', daemonSocket);
          } catch (error) {
            console.error('❌ Failed to create Daemon WebSocket:', error);
            console.error('❌ URL attempted:', import.meta.env.VITE_DAEMON_SOCKET);
            // Beim Konstruktionsfehler ebenfalls Fallback versuchen
            if (attemptIndex < protocols.length - 1) {
              attemptIndex += 1;
              console.warn('🔄 Fallback: Konstruktion ohne Subprotokoll...');
              tryConnectWithProtocol();
              return;
            }
            retryConnection(connectDaemonSocket);
          }
        };

        tryConnectWithProtocol();
      };

      let retryCount = 0;
      const maxRetries = 15; // Increased max retries
      const retryConnection = (reconnectFn) => {
        if (retryCount >= maxRetries) {
          console.error('❌ Max retry attempts reached for Daemon WebSocket');
          // Reset counter after a longer delay to allow for network recovery
          setTimeout(() => {
            retryCount = 0;
            console.log('🔄 Resetting Daemon WebSocket retry counter - attempting reconnection');
            reconnectFn();
          }, 60000); // Wait 1 minute before resetting
          return;
        }
        retryCount++;
        const delay = Math.min(1000 * Math.pow(1.5, retryCount - 1), 30000); // Exponential backoff, max 30s
        console.log(`🔄 Retrying Daemon WebSocket connection in ${delay}ms (attempt ${retryCount}/${maxRetries})`);
        setTimeout(() => {
          reconnectFn();
        }, delay);
      };
      connectDaemonSocket();
    },
    setLanguage({ commit }, language) {
      commit('setLanguage', language);
    },
    async loadMenu({ commit }) {
      try {
        const menu = await loadMenu();
        commit('setMenu', menu);
      } catch (err) {
        console.error(err);
        commit('setMenu', []);
      }
    },
  },
  getters: {
    isLoggedIn: state => state.isLoggedIn,
    user: state => state.user,
    language: state => state.language,
    menu: state => state.menu,
    socket: state => state.socket,
    daemonSocket: state => state.daemonSocket,
    menuNeedsUpdate: state => state.menuNeedsUpdate,
    connectionStatus: state => state.connectionStatus,
  },
  modules: {
    dialogs,
  },
});

if (store.state.isLoggedIn && store.state.user) {
  store.dispatch('initializeSocket');
  store.dispatch('initializeDaemonSocket');
}

export default store;
