import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { io } from 'socket.io-client';

export const useChatStore = defineStore('chat', () => {
  const LOGOUT_MARKER_KEY = 'singlechat_logged_out';

  // State
  const isLoggedIn = ref(false);
  const userName = ref('');
  const gender = ref('');
  const age = ref(0);
  const country = ref('');
  const isoCountryCode = ref('');
  const sessionId = ref('');
  const socket = ref(null);
  const users = ref([]);
  const currentConversation = ref(null);
  const messages = ref([]);
  const currentView = ref('chat');
  const searchResults = ref([]);
  const inboxResults = ref([]);
  const historyResults = ref([]);
  const unreadChatsCount = ref(0);
  const errorMessage = ref(null);
  const commandTable = ref(null);
  const remainingSecondsToTimeout = ref(1800);
  const awaitingLoginUsername = ref(false);
  const awaitingLoginPassword = ref(false);
  const searchData = ref({
    nameIncludes: '',
    minAge: null,
    maxAge: null,
    genders: [],
    selectedCountries: [], // Übersetzte Namen (für UI)
    selectedCountriesEnglish: [] // Englische Namen (für Server)
  });
  let timeoutTimer = null;
  const TIMEOUT_SECONDS = 1800; // 30 Minuten

  // Computed
  const currentConversationWith = computed(() => {
    if (!currentConversation.value) return null;
    return currentConversation.value;
  });

  // Actions
  function connectWebSocket() {
    return new Promise((resolve, reject) => {
      // Schließe alte Verbindung, falls vorhanden
      if (socket.value) {
        try {
          socket.value.disconnect();
        } catch (e) {
          // Ignoriere Fehler beim Schließen
        }
        socket.value = null;
      }
      
      let url;
      
      if (import.meta.env.DEV) {
        // Socket.IO läuft jetzt auf dem gleichen Port wie Express
        url = 'http://localhost:3300';
      } else {
        // In Production: Socket.IO läuft über den gleichen Host/Port wie die Webseite
        // Apache leitet alles an den Backend-Server weiter
        url = window.location.origin;
      }
      
      console.log('=== Socket.IO-Verbindung ===');
      console.log('Versuche Socket.IO-Verbindung zu:', url);
      console.log('Aktuelle Seite:', window.location.href);
      console.log('DEV-Modus:', import.meta.env.DEV);
      
      let timeoutId;
      let resolved = false;
      
      try {
        const socketInstance = io(url, {
          transports: ['polling'], // Nur Polling verwenden, um WebSocket-Probleme zu vermeiden
          reconnection: true,
          reconnectionAttempts: 5,
          reconnectionDelay: 1000,
          upgrade: false, // Kein Upgrade zu WebSocket
          rememberUpgrade: false,
          withCredentials: true // Wichtig für Cookies/Sessions
        });
        
        // Timeout nach 5 Sekunden
        timeoutId = setTimeout(() => {
          if (!resolved) {
            resolved = true;
            socketInstance.disconnect();
            reject(new Error('Socket.IO-Verbindung-Timeout: Server antwortet nicht. Bitte stelle sicher, dass der Server auf Port 3300 läuft.'));
          }
        }, 5000);
        
        socketInstance.on('connect', async () => {
          if (!resolved) {
            resolved = true;
            clearTimeout(timeoutId);
            console.log('Socket.IO-Verbindung erfolgreich');
            socket.value = socketInstance;
            
            // Hole Express-Session-ID und sende sie an den Server
            try {
              const response = await fetch('/api/session', {
                credentials: 'include'
              });
              if (response.ok) {
                const data = await response.json();
                if (data.sessionId) {
                  console.log('Socket.IO Connect - Sende Express-Session-ID:', data.sessionId);
                  socketInstance.emit('setSessionId', { expressSessionId: data.sessionId });
                }
              }
            } catch (error) {
              console.error('Fehler beim Abrufen der Session-ID:', error);
            }
            
            resolve(socketInstance);
          }
        });
        
        socketInstance.on('connected', (data) => {
          console.log('Connected-Nachricht empfangen:', data);
          sessionId.value = data.sessionId;
          
          // Wenn bereits eingeloggt, Login-Status wiederherstellen
          if (data.loggedIn && data.user) {
            isLoggedIn.value = true;
            userName.value = data.user.userName;
            gender.value = data.user.gender;
            age.value = data.user.age;
            country.value = data.user.country;
            isoCountryCode.value = data.user.isoCountryCode;
            startTimeoutTimer();
          }
        });
        
        socketInstance.on('disconnect', (reason) => {
          console.log('Socket.IO-Verbindung getrennt:', reason);
          socket.value = null;
        });
        
        socketInstance.on('connect_error', (error) => {
          console.error('Socket.IO Verbindungsfehler:', error);
          if (!resolved) {
            resolved = true;
            clearTimeout(timeoutId);
            reject(new Error('Socket.IO-Verbindung fehlgeschlagen: ' + error.message));
          }
        });
        
        // Event-Handler für verschiedene Nachrichtentypen
        socketInstance.on('loginSuccess', (data) => {
          handleWebSocketMessage({ type: 'loginSuccess', ...data });
        });
        
        socketInstance.on('userList', (data) => {
          handleWebSocketMessage({ type: 'userList', ...data });
        });
        
        socketInstance.on('message', (data) => {
          handleWebSocketMessage({ type: 'message', ...data });
        });
        
        socketInstance.on('messageSent', (data) => {
          handleWebSocketMessage({ type: 'messageSent', ...data });
        });
        
        socketInstance.on('messageSent', (data) => {
          handleWebSocketMessage({ type: 'messageSent', ...data });
        });
        
        socketInstance.on('conversation', (data) => {
          handleWebSocketMessage({ type: 'conversation', ...data });
        });
        
        socketInstance.on('searchResults', (data) => {
          handleWebSocketMessage({ type: 'searchResults', ...data });
        });
        
        socketInstance.on('inboxResults', (data) => {
          handleWebSocketMessage({ type: 'inboxResults', ...data });
        });
        
        socketInstance.on('historyResults', (data) => {
          handleWebSocketMessage({ type: 'historyResults', ...data });
        });
        
        socketInstance.on('commandResult', (data) => {
          handleWebSocketMessage({ type: 'commandResult', ...data });
        });
        
        socketInstance.on('commandTable', (data) => {
          handleWebSocketMessage({ type: 'commandTable', ...data });
        });
        
        socketInstance.on('unreadChats', (data) => {
          handleWebSocketMessage({ type: 'unreadChats', ...data });
        });
        
        socketInstance.on('error', (data) => {
          handleWebSocketMessage({ type: 'error', ...data });
        });
        
        console.log('Socket.IO-Objekt erstellt');
      } catch (error) {
        if (timeoutId) clearTimeout(timeoutId);
        console.error('Fehler beim Erstellen der Socket.IO-Verbindung:', error);
        reject(new Error('Fehler beim Erstellen der Socket.IO-Verbindung: ' + error.message));
      }
    });
  }

  function handleWebSocketMessage(data) {
    console.log('WebSocket-Nachricht empfangen:', data.type);
    
    switch (data.type) {
      case 'connected':
        sessionId.value = data.sessionId;
        break;
      case 'loginSuccess':
        isLoggedIn.value = true;
        userName.value = data.user.userName;
        gender.value = data.user.gender;
        age.value = data.user.age;
        country.value = data.user.country;
        isoCountryCode.value = data.user.isoCountryCode;
        sessionId.value = data.sessionId;
        // Wichtig: Beim frischen Login den Timeout-Timer starten
        startTimeoutTimer();
        break;
      case 'userList':
        users.value = data.users;
        // Aktualisiere Suchergebnisse, falls eine Suche aktiv ist
        updateSearchResults();
        break;
      case 'message':
        // Debug-Logging für empfangene Nachrichten
        if (data.isImage) {
          console.log('[Bild empfangen] Von:', data.from, 'URL:', data.imageUrl || data.message);
        }
        
        // Sound abspielen bei neuer Nachricht (nur wenn nicht selbst gesendet)
        if (!data.self) {
          try {
            const audio = new Audio('/static/newmessage.mp3');
            audio.play().catch(err => {
              // Ignoriere Fehler (z.B. wenn Browser Auto-Play blockiert)
              console.log('Sound konnte nicht abgespielt werden:', err);
            });
          } catch (error) {
            console.log('Fehler beim Abspielen des Sounds:', error);
          }
        }
        
        if (currentConversation.value === data.from) {
          const newMessage = {
            from: data.from,
            message: data.imageUrl || data.message, // Verwende URL für Bilder
            timestamp: data.timestamp,
            self: false,
            isImage: data.isImage || false,
            imageType: data.imageType || null,
            imageUrl: data.imageUrl || null,
            imageCode: data.imageCode || null
          };
          
          console.log('[Nachricht hinzugefügt]', newMessage);
          messages.value.push(newMessage);
        } else {
          console.log('[Nachricht ignoriert] Aktuelle Konversation:', currentConversation.value, 'Nachricht von:', data.from);
        }
        // Timeout zurücksetzen bei empfangener Nachricht
        resetTimeoutTimer();
        break;
      case 'messageSent':
        // Bestätigung, dass Nachricht gesendet wurde
        break;
      case 'conversation':
        currentConversation.value = data.with;
        messages.value = data.messages.map(msg => ({
          from: msg.from,
          message: msg.imageUrl || msg.message, // Verwende URL für Bilder
          timestamp: msg.timestamp,
          self: msg.from === userName.value,
          isImage: msg.isImage || false,
          imageType: msg.imageType || null,
          imageUrl: msg.imageUrl || null,
          imageCode: msg.imageCode || null
        }));
        break;
      case 'searchResults':
        searchResults.value = data.results;
        break;
      case 'inboxResults':
        inboxResults.value = data.results;
        break;
      case 'historyResults':
        historyResults.value = data.results;
        break;
      case 'commandResult': {
        const lines = Array.isArray(data.lines) ? data.lines : [];
        const kind = data.kind || 'info';

        if (kind === 'loginPromptUsername') {
          awaitingLoginUsername.value = true;
          awaitingLoginPassword.value = false;
        } else if (kind === 'loginPromptPassword') {
          awaitingLoginUsername.value = false;
          awaitingLoginPassword.value = true;
        } else if (kind === 'loginSuccess' || kind === 'loginError' || kind === 'loginAbort' || kind === 'loginLogout') {
          awaitingLoginUsername.value = false;
          awaitingLoginPassword.value = false;
        }

        // Command-Ausgaben immer global anzeigen, nicht im Chatverlauf.
        errorMessage.value = lines.join(' | ');
        setTimeout(() => {
          errorMessage.value = null;
        }, 5000);
        break;
      }
      case 'commandTable': {
        const title = data.title || 'Ausgabe';
        const columns = Array.isArray(data.columns) ? data.columns : [];
        const rows = Array.isArray(data.rows) ? data.rows : [];
        commandTable.value = { title, columns, rows };
        // Tabelle ist persistent; temporäre Fehlermeldung löschen
        errorMessage.value = null;
        break;
      }
      case 'unreadChats':
        unreadChatsCount.value = data.count || 0;
        break;
      case 'error':
        console.error('Server-Fehler:', data.message);
        errorMessage.value = data.message;
        // Fehlermeldung nach 5 Sekunden automatisch entfernen
        setTimeout(() => {
          errorMessage.value = null;
        }, 5000);
        break;
    }
  }

  async function login(userNameVal, genderVal, ageVal, countryVal) {
    try {
      window.localStorage.removeItem(LOGOUT_MARKER_KEY);
    } catch (error) {
      console.warn('Logout-Marker konnte nicht entfernt werden:', error);
    }

    // Stelle sicher, dass Socket.IO verbunden ist
    if (!socket.value || !socket.value.connected) {
      console.log('Socket.IO nicht verbunden, versuche Verbindung herzustellen...');
      try {
        await connectWebSocket();
        // Warte kurz, damit die Verbindung vollständig hergestellt ist
        await new Promise(resolve => setTimeout(resolve, 100));
      } catch (error) {
        console.error('Fehler beim Verbinden mit Socket.IO:', error);
        alert('Verbindung zum Server fehlgeschlagen. Bitte stelle sicher, dass der Server läuft.');
        return;
      }
    }
    
    // Prüfe nochmal, ob die Verbindung jetzt besteht
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO-Verbindung konnte nicht hergestellt werden');
      alert('Verbindung zum Server fehlgeschlagen. Bitte stelle sicher, dass der Server läuft.');
      return;
    }
    
    // Hole Express-Session-ID vom Server
    let expressSessionId = null;
    try {
      const response = await fetch('/api/session', {
        credentials: 'include'
      });
      if (response.ok) {
        const data = await response.json();
        expressSessionId = data.sessionId;
        console.log('Login - Express-Session-ID erhalten:', expressSessionId);
      }
    } catch (error) {
      console.error('Fehler beim Abrufen der Session-ID:', error);
    }
    
    socket.value.emit('login', {
      userName: userNameVal,
      gender: genderVal,
      age: ageVal,
      country: countryVal,
      expressSessionId: expressSessionId
    });
  }

  function sendMessage(toUserName, message, options = {}) {
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO nicht verbunden');
      return;
    }
    
    const messageId = Date.now().toString();
    const trimmed = message.trim();
    const isCommand = trimmed.startsWith('/');
    socket.value.emit('message', {
      toUserName,
      message: trimmed,
      messageId
    });
    
    const suppressLocal = !!options.suppressLocal || isCommand || awaitingLoginUsername.value || awaitingLoginPassword.value;

    // Lokal hinzufügen (außer bei Commands oder sensiblen Eingaben wie Login)
    if (!isCommand && !suppressLocal) {
      messages.value.push({
        from: userName.value,
        message: trimmed,
        timestamp: new Date().toISOString(),
        self: true
      });
    }
    
    // Timeout zurücksetzen bei Aktivität
    resetTimeoutTimer();
  }

  function sendImage(toUserName, imageCode, imageUrl) {
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO nicht verbunden');
      return;
    }
    
    if (!toUserName) {
      console.error('Empfänger fehlt');
      return;
    }
    
    const messageId = Date.now().toString();
    socket.value.emit('message', {
      toUserName,
      message: imageCode, // Nur der Code, nicht das gesamte Bild
      messageId,
      isImage: true,
      imageUrl: imageUrl // URL für das Bild
    });
    
    // Lokal hinzufügen (mit URL)
    messages.value.push({
      from: userName.value,
      message: imageUrl, // Verwende URL statt Code für lokale Anzeige
      timestamp: new Date().toISOString(),
      self: true,
      isImage: true,
      imageCode: imageCode
    });
    
    // Timeout zurücksetzen bei Aktivität
    resetTimeoutTimer();
  }

  function requestConversation(withUserName) {
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO nicht verbunden');
      errorMessage.value = 'Socket.IO nicht verbunden';
      setTimeout(() => {
        errorMessage.value = null;
      }, 5000);
      return;
    }
    
    // Fehlermeldung zurücksetzen
    errorMessage.value = null;
    
    socket.value.emit('requestConversation', {
      withUserName
    });
    
    currentConversation.value = withUserName;
    currentView.value = 'chat';
  }

  function userSearch(searchDataPayload) {
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO nicht verbunden');
      errorMessage.value = 'Socket.IO nicht verbunden';
      setTimeout(() => {
        errorMessage.value = null;
      }, 5000);
      return;
    }
    
    // Fehlermeldung zurücksetzen
    errorMessage.value = null;
    
    // Speichere Suchparameter für spätere Aktualisierungen
    // Hinweis: selectedCountries wird in SearchView.vue verwaltet und enthält übersetzte Namen
    // Für updateSearchResults speichern wir auch die englischen Länder-Namen
    searchData.value.nameIncludes = searchDataPayload.nameIncludes || '';
    searchData.value.minAge = searchDataPayload.minAge || null;
    searchData.value.maxAge = searchDataPayload.maxAge || null;
    searchData.value.genders = searchDataPayload.genders || [];
    // Speichere die englischen Länder-Namen für spätere Aktualisierungen
    if (searchDataPayload.countries) {
      searchData.value.selectedCountriesEnglish = searchDataPayload.countries;
    }
    
    socket.value.emit('userSearch', searchDataPayload);
    resetTimeoutTimer(); // Aktivität zurücksetzen
  }

  function updateSearchResults() {
    // Aktualisiere Suchergebnisse nur, wenn eine Suche aktiv ist
    // Prüfe, ob der Benutzer auf der Suchseite ist UND ob es bereits Suchergebnisse gibt
    const hasSearchResults = searchResults.value && searchResults.value.length > 0;
    const hasSearchParams = searchData.value.nameIncludes || 
                           searchData.value.minAge || 
                           searchData.value.maxAge || 
                           (searchData.value.selectedCountries && searchData.value.selectedCountries.length > 0) ||
                           (searchData.value.genders && searchData.value.genders.length > 0);
    
    // Aktualisiere nur, wenn der Benutzer auf der Suchseite ist UND (Ergebnisse vorhanden ODER Parameter gesetzt)
    if (currentView.value !== 'search' || (!hasSearchResults && !hasSearchParams)) {
      return;
    }
    
    // Führe die Suche erneut aus, um aktuelle Ergebnisse zu erhalten
    // Verwende die englischen Länder-Namen, die beim letzten Suchvorgang gespeichert wurden
    const searchPayload = {
      nameIncludes: searchData.value.nameIncludes || null,
      minAge: searchData.value.minAge || null,
      maxAge: searchData.value.maxAge || null,
      countries: searchData.value.selectedCountriesEnglish && searchData.value.selectedCountriesEnglish.length > 0 
        ? searchData.value.selectedCountriesEnglish 
        : null,
      genders: searchData.value.genders && searchData.value.genders.length > 0 
        ? searchData.value.genders 
        : null
    };
    
    // Sende Suchanfrage erneut an den Server
    if (socket.value && socket.value.connected) {
      socket.value.emit('userSearch', searchPayload);
    }
  }

  function requestHistory() {
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO nicht verbunden');
      return;
    }
    
    socket.value.emit('requestHistory');
  }

  function requestOpenConversations() {
    if (!socket.value || !socket.value.connected) {
      console.error('Socket.IO nicht verbunden');
      return;
    }
    
    socket.value.emit('requestOpenConversations');
  }

  function clearCommandTable() {
    commandTable.value = null;
  }

  function setView(view) {
    currentView.value = view;
    
    // Search-Ergebnisse NICHT zurücksetzen, damit sie beim Zurückkehren erhalten bleiben
    if (view === 'search') {
      // Wenn zur Suchseite zurückgekehrt wird, aktualisiere die Suchergebnisse
      // falls bereits Suchparameter vorhanden sind
      updateSearchResults();
    } else if (view === 'inbox') {
      requestOpenConversations();
    } else if (view === 'history') {
      requestHistory();
    }
  }

  async function logout() {
    try {
      window.localStorage.setItem(LOGOUT_MARKER_KEY, '1');
    } catch (error) {
      console.warn('Logout-Marker konnte nicht gespeichert werden:', error);
    }

    try {
      await fetch('/api/logout', {
        method: 'POST',
        credentials: 'include'
      });
    } catch (error) {
      console.error('Logout-Request fehlgeschlagen:', error);
    }

    stopTimeoutTimer();
    isLoggedIn.value = false;
    userName.value = '';
    gender.value = '';
    age.value = 0;
    country.value = '';
    isoCountryCode.value = '';
    sessionId.value = '';
    users.value = [];
    currentConversation.value = null;
    messages.value = [];
    currentView.value = 'chat';
    searchResults.value = [];
    inboxResults.value = [];
    historyResults.value = [];
    commandTable.value = null;
    searchData.value = {
      nameIncludes: '',
      minAge: null,
      maxAge: null,
      genders: [],
      selectedCountries: [],
      selectedCountriesEnglish: []
    };
    
    if (socket.value) {
      socket.value.disconnect();
      socket.value = null;
    }
  }

  function startTimeoutTimer() {
    stopTimeoutTimer(); // Stoppe alten Timer, falls vorhanden
    remainingSecondsToTimeout.value = TIMEOUT_SECONDS;
    
    timeoutTimer = setInterval(() => {
      remainingSecondsToTimeout.value--;
      
      if (remainingSecondsToTimeout.value <= 0) {
        stopTimeoutTimer();
        // Auto-Logout
        console.log('Timeout erreicht - automatischer Logout');
        logout();
      }
    }, 1000); // Jede Sekunde aktualisieren
  }
  
  function resetTimeoutTimer() {
    if (isLoggedIn.value && timeoutTimer) {
      remainingSecondsToTimeout.value = TIMEOUT_SECONDS;
    }
  }
  
  function stopTimeoutTimer() {
    if (timeoutTimer) {
      clearInterval(timeoutTimer);
      timeoutTimer = null;
    }
    remainingSecondsToTimeout.value = TIMEOUT_SECONDS;
  }

  async function restoreSession() {
    try {
      try {
        if (window.localStorage.getItem(LOGOUT_MARKER_KEY) === '1') {
          console.log('restoreSession: Automatische Wiederherstellung nach Logout unterdrueckt');
          return false;
        }
      } catch (error) {
        console.warn('Logout-Marker konnte nicht gelesen werden:', error);
      }

      console.log('restoreSession: Starte Session-Wiederherstellung...');
      const response = await fetch('/api/session', {
        credentials: 'include' // Wichtig für Cookies
      });
      
      if (!response.ok) {
        console.log('restoreSession: Response nicht OK:', response.status);
        return false;
      }
      
      const data = await response.json();
      console.log('restoreSession: Antwort vom Server:', data);
      
      if (data.loggedIn && data.user) {
        console.log('restoreSession: Session gefunden, stelle Login-Status wieder her...');
        // Session wiederherstellen
        isLoggedIn.value = true;
        userName.value = data.user.userName;
        gender.value = data.user.gender;
        age.value = data.user.age;
        country.value = data.user.country;
        isoCountryCode.value = data.user.isoCountryCode;
        sessionId.value = data.user.sessionId;
        
        console.log('restoreSession: Login-Status wiederhergestellt:', {
          userName: userName.value,
          sessionId: sessionId.value
        });
        
        // WebSocket-Verbindung herstellen
        try {
          await connectWebSocket();
          startTimeoutTimer();
        } catch (error) {
          console.error('Fehler beim Wiederherstellen der WebSocket-Verbindung:', error);
        }
        
        return true;
      }
      
      console.log('restoreSession: Keine gültige Session gefunden');
      return false;
    } catch (error) {
      console.error('Fehler beim Wiederherstellen der Session:', error);
      return false;
    }
  }

  return {
    // State
    isLoggedIn,
    userName,
    gender,
    age,
    country,
    isoCountryCode,
    sessionId,
    socket,
    users,
    currentConversation,
    messages,
    currentView,
        searchResults,
        inboxResults,
        historyResults,
        unreadChatsCount,
        remainingSecondsToTimeout,
        errorMessage,
        commandTable,
        searchData,
        awaitingLoginUsername,
        awaitingLoginPassword,
    // Computed
    currentConversationWith,
    // Actions
    connectWebSocket,
    login,
    sendMessage,
    sendImage,
    requestConversation,
    userSearch,
    requestHistory,
    requestOpenConversations,
    clearCommandTable,
    setView,
    logout,
    restoreSession
  };
});
