import { readFileSync, writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { parse } from 'csv-parse/sync';
import multer from 'multer';
import crypto from 'crypto';

import axios from 'axios';
import { getSessionStatus, getClientsMap, getSessionIdForSocket, extractSessionId } from './broadcast.js';
import { verifyChatUser } from './chat-auth.js';
import { loadFeedback, saveFeedback, createFeedbackEntry } from './feedback-store.js';

// __dirname für ES-Module
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Bild-Upload-Konfiguration (temporäres Verzeichnis)
const uploadsDir = join(__dirname, '../tmp');
if (!existsSync(uploadsDir)) {
  mkdirSync(uploadsDir, { recursive: true });
}

// Map: Code -> Bild-Info (für temporäre Speicherung)
const imageCodes = new Map();

// Multer-Konfiguration für Bild-Upload
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, uploadsDir);
  },
  filename: (req, file, cb) => {
    // Generiere eindeutigen Code
    const code = crypto.randomBytes(16).toString('hex');
    const ext = file.originalname.split('.').pop();
    cb(null, `${code}.${ext}`);
  }
});

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB Limit
  },
  fileFilter: (req, file, cb) => {
    // Nur Bilder erlauben
    if (file.mimetype.startsWith('image/')) {
      cb(null, true);
    } else {
      cb(new Error('Nur Bilder sind erlaubt'), false);
    }
  }
});

export function setupRoutes(app, __dirname) {
  // Health-Check-Endpoint
  app.get('/api/health', (req, res) => {
    res.json({ status: 'ok', timestamp: new Date().toISOString() });
  });

  app.post('/api/logout', (req, res) => {
    try {
      const sessionId = req.sessionID;
      const clientsMap = getClientsMap();
      const client = clientsMap.get(sessionId);

      if (client?.socket) {
        try {
          client.socket.disconnect(true);
        } catch (error) {
          console.warn('Logout: Socket konnte nicht sauber getrennt werden:', error);
        }
      }

      if (sessionId) {
        clientsMap.delete(sessionId);
      }

      req.session.destroy((error) => {
        if (error) {
          console.error('Logout: Session konnte nicht zerstört werden:', error);
          return res.status(500).json({ success: false });
        }

        res.clearCookie('connect.sid');
        res.json({ success: true });
      });
    } catch (error) {
      console.error('Logout-Fehler:', error);
      res.status(500).json({ success: false });
    }
  });

  app.get('/api/feedback', (req, res) => {
    try {
      const feedback = loadFeedback(__dirname)
        .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
      res.json({
        items: feedback,
        admin: !!req.session.feedbackAdmin
      });
    } catch (error) {
      console.error('Fehler beim Laden des Feedbacks:', error);
      res.status(500).json({ error: 'Fehler beim Laden des Feedbacks' });
    }
  });

  app.get('/api/feedback/admin-status', (req, res) => {
    res.json({
      authenticated: !!req.session.feedbackAdmin,
      username: req.session.feedbackAdmin?.username || null
    });
  });

  app.post('/api/feedback', (req, res) => {
    try {
      const ageValue = req.body.age === '' || req.body.age === null || req.body.age === undefined
        ? null
        : Number.parseInt(req.body.age, 10);

      const entry = createFeedbackEntry({
        name: req.body.name,
        age: Number.isNaN(ageValue) ? null : ageValue,
        country: req.body.country,
        gender: req.body.gender,
        comment: req.body.comment
      });

      if (!entry.comment) {
        return res.status(400).json({ error: 'Kommentar ist erforderlich.' });
      }

      const feedback = loadFeedback(__dirname);
      feedback.push(entry);
      saveFeedback(__dirname, feedback);

      res.status(201).json({ success: true, item: entry });
    } catch (error) {
      console.error('Fehler beim Speichern des Feedbacks:', error);
      res.status(500).json({ error: 'Fehler beim Speichern des Feedbacks' });
    }
  });

  app.post('/api/feedback/admin-login', (req, res) => {
    try {
      const { username, password } = req.body || {};
      const auth = verifyChatUser(__dirname, username, password);

      if (!auth) {
        return res.status(401).json({ error: 'Login fehlgeschlagen.' });
      }

      req.session.feedbackAdmin = {
        username: auth.username
      };

      res.json({ success: true, username: auth.username });
    } catch (error) {
      console.error('Fehler beim Feedback-Admin-Login:', error);
      res.status(500).json({ error: 'Fehler beim Login' });
    }
  });

  app.post('/api/feedback/admin-logout', (req, res) => {
    delete req.session.feedbackAdmin;
    res.json({ success: true });
  });

  app.delete('/api/feedback/:id', (req, res) => {
    try {
      if (!req.session.feedbackAdmin) {
        return res.status(403).json({ error: 'Nicht erlaubt.' });
      }

      const feedback = loadFeedback(__dirname);
      const nextFeedback = feedback.filter((item) => item.id !== req.params.id);

      if (nextFeedback.length === feedback.length) {
        return res.status(404).json({ error: 'Eintrag nicht gefunden.' });
      }

      saveFeedback(__dirname, nextFeedback);
      res.json({ success: true });
    } catch (error) {
      console.error('Fehler beim Löschen des Feedbacks:', error);
      res.status(500).json({ error: 'Fehler beim Löschen des Feedbacks' });
    }
  });
  
  // Bild-Upload-Endpoint
  app.post('/api/upload-image', upload.single('image'), (req, res) => {
    try {
      if (!req.file) {
        return res.status(400).json({ error: 'Kein Bild hochgeladen' });
      }
      
      // WICHTIG: Modifiziere req.session, damit Express-Session das Cookie setzt
      // (saveUninitialized: false bedeutet, dass das Cookie nur gesetzt wird, wenn req.session modifiziert wird)
      if (!req.session.initialized) {
        req.session.initialized = true;
      }
      
      // Prüfe, ob Benutzer eingeloggt ist
      // Versuche zuerst, Session-ID aus Cookie zu extrahieren (wie beim Login)
      let sessionId = extractSessionId(req);
      
      // Wenn extractSessionId eine UUID generiert hat (kein Cookie gefunden),
      // versuche req.sessionID zu verwenden
      const isUUID = sessionId && sessionId.length === 36 && sessionId.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
      
      if (isUUID) {
        // extractSessionId hat eine UUID generiert, verwende req.sessionID stattdessen
        sessionId = req.sessionID;
        if (sessionId && sessionId.startsWith('s:')) {
          const parts = sessionId.split('.');
          if (parts.length > 0) {
            sessionId = parts[0].substring(2); // Entferne 's:' Präfix
          }
        }
      }
      
      console.log(`[Bild-Upload] Session-ID: ${sessionId}, req.sessionID (roh): ${req.sessionID}, Cookie vorhanden: ${!isUUID}, Alle Clients:`, Array.from(getClientsMap().keys()));
      
      const clientsMap = getClientsMap();
      let client = clientsMap.get(sessionId);
      
      // Wenn kein Client gefunden wurde und req.sessionID vorhanden ist, versuche auch mit bereinigter req.sessionID
      if (!client && req.sessionID) {
        const cleanedSessionId = req.sessionID.startsWith('s:') ? req.sessionID.split('.')[0].substring(2) : req.sessionID;
        if (cleanedSessionId !== sessionId) {
          client = clientsMap.get(cleanedSessionId);
          if (client) {
            console.log(`[Bild-Upload] Client gefunden mit bereinigter req.sessionID: ${cleanedSessionId}`);
            sessionId = cleanedSessionId;
          }
        }
      }
      
      // Wenn kein Client gefunden wurde, versuche Fallback: Finde den zuletzt aktiven Client mit aktivem Socket
      if (!client || !client.userName) {
        console.log(`[Bild-Upload] Client nicht gefunden für Session-ID: ${sessionId}`);
        console.log(`[Bild-Upload] Cookies: ${req.headers.cookie || 'keine'}`);
        
        // Fallback: Suche nach dem zuletzt aktiven Client mit aktivem Socket
        let fallbackClient = null;
        let latestActivity = 0;
        
        for (const [sid, c] of clientsMap.entries()) {
          if (c.userName && c.socket && c.socket.connected) {
            const activityTime = c.lastActivity ? c.lastActivity.getTime() : 0;
            if (activityTime > latestActivity) {
              latestActivity = activityTime;
              fallbackClient = c;
            }
          }
        }
        
        // Wenn ein Fallback-Client gefunden wurde und er kürzlich aktiv war (innerhalb der letzten 5 Minuten)
        if (fallbackClient && latestActivity > Date.now() - 5 * 60 * 1000) {
          console.log(`[Bild-Upload] Fallback: Verwende zuletzt aktiven Client: ${fallbackClient.userName} (Session-ID: ${fallbackClient.sessionId})`);
          client = fallbackClient;
        } else {
          // Lösche hochgeladenes Bild, wenn nicht eingeloggt
          unlinkSync(req.file.path);
          return res.status(401).json({ error: 'Nicht eingeloggt' });
        }
      }
      
      // Generiere eindeutigen Code für das Bild
      const code = req.file.filename.split('.')[0];
      const imageInfo = {
        code: code,
        filename: req.file.filename,
        originalName: req.file.originalname,
        mimetype: req.file.mimetype,
        size: req.file.size,
        uploadedBy: client.userName,
        uploadedAt: new Date().toISOString(),
        expiresAt: new Date(Date.now() + 6 * 60 * 60 * 1000) // 6 Stunden
      };
      
      // Speichere Bild-Info
      imageCodes.set(code, imageInfo);
      
      console.log(`[Bild-Upload] Bild hochgeladen von ${client.userName}, Code: ${code}`);
      
      res.json({
        success: true,
        code: code,
        url: `/api/image/${code}`
      });
    } catch (error) {
      console.error('Fehler beim Bild-Upload:', error);
      if (req.file && existsSync(req.file.path)) {
        unlinkSync(req.file.path);
      }
      res.status(500).json({ error: 'Fehler beim Hochladen des Bildes' });
    }
  });
  
  // Bild-Download-Endpoint (mit Code)
  app.get('/api/image/:code', (req, res) => {
    try {
      const { code } = req.params;
      const imageInfo = imageCodes.get(code);
      
      if (!imageInfo) {
        return res.status(404).json({ error: 'Bild nicht gefunden' });
      }
      
      // Prüfe Ablaufzeit
      if (new Date() > imageInfo.expiresAt) {
        // Lösche abgelaufenes Bild
        const filePath = join(uploadsDir, imageInfo.filename);
        if (existsSync(filePath)) {
          unlinkSync(filePath);
        }
        imageCodes.delete(code);
        return res.status(410).json({ error: 'Bild abgelaufen' });
      }
      
      // Prüfe, ob Benutzer eingeloggt ist (optional, für zusätzliche Sicherheit)
      const sessionId = req.sessionID;
      const clientsMap = getClientsMap();
      const client = clientsMap.get(sessionId);
      
      // Wenn eingeloggt, prüfe ob Benutzer berechtigt ist (optional)
      // Für jetzt erlauben wir allen eingeloggten Benutzern den Zugriff
      
      const filePath = join(uploadsDir, imageInfo.filename);
      if (!existsSync(filePath)) {
        imageCodes.delete(code);
        return res.status(404).json({ error: 'Bilddatei nicht gefunden' });
      }
      
      // Setze Content-Type
      res.setHeader('Content-Type', imageInfo.mimetype);
      res.setHeader('Content-Disposition', `inline; filename="${imageInfo.originalName}"`);
      
      // Sende Bild
      const imageData = readFileSync(filePath);
      res.send(imageData);
    } catch (error) {
      console.error('Fehler beim Laden des Bildes:', error);
      res.status(500).json({ error: 'Fehler beim Laden des Bildes' });
    }
  });
  
  // Cleanup-Funktion für abgelaufene Bilder (wird regelmäßig aufgerufen)
  setInterval(() => {
    const now = new Date();
    let deletedCount = 0;
    for (const [code, info] of imageCodes.entries()) {
      if (now > info.expiresAt) {
        const filePath = join(uploadsDir, info.filename);
        if (existsSync(filePath)) {
          unlinkSync(filePath);
        }
        imageCodes.delete(code);
        deletedCount++;
      }
    }
    if (deletedCount > 0) {
      console.log(`[Bild-Cleanup] ${deletedCount} abgelaufene Bild(er) gelöscht`);
    }
  }, 30 * 60 * 1000); // Alle 30 Minuten prüfen

  // Session-Status-Endpoint
  app.get('/api/session', (req, res) => {
    try {
      // WICHTIG: Modifiziere req.session, damit Express-Session das Cookie setzt
      // (saveUninitialized: false bedeutet, dass das Cookie nur gesetzt wird, wenn req.session modifiziert wird)
      if (!req.session.initialized) {
        req.session.initialized = true;
      }
      
      const sessionId = req.sessionID;
      console.log('Session-Check - SessionID:', sessionId);
      console.log('Session-Check - Alle Clients:', Array.from(getClientsMap().keys()));
      
      // Prüfe zuerst in der clients Map
      const clientsMap = getClientsMap();
      let client = clientsMap.get(sessionId);
      
      // Wenn kein Client mit dieser Session-ID gefunden wurde, aber es gibt Clients,
      // die bereits eingeloggt sind, könnte es sein, dass die Session-ID beim Reload geändert wurde.
      // In diesem Fall sollten wir den Client mit der Express-Session-ID verknüpfen.
      // Aber wir können nicht sicher sein, welcher Client zu welcher Session gehört,
      // daher geben wir einfach die Session-ID zurück und lassen den Client beim setSessionId
      // den richtigen Client finden.
      
      if (client && client.userName) {
        console.log('Session-Check - Client gefunden:', client.userName);
        res.json({ 
          loggedIn: true,
          sessionId: sessionId, // Wichtig: Sende Session-ID zurück
          user: {
            sessionId: client.sessionId,
            userName: client.userName,
            gender: client.gender,
            age: client.age,
            country: client.country,
            isoCountryCode: client.isoCountryCode
          }
        });
      } else {
        console.log('Session-Check - Kein Client gefunden für SessionID:', sessionId);
        // Prüfe auch alle Clients, um zu sehen, ob es ein Mismatch gibt
        for (const [sid, c] of clientsMap.entries()) {
          if (c.userName) {
            console.log('Session-Check - Gefundener Client:', sid, c.userName);
          }
        }
        // Sende Session-ID zurück, auch wenn nicht eingeloggt (für Login)
        res.json({ loggedIn: false, sessionId: sessionId });
      }
    } catch (error) {
      console.error('Fehler beim Prüfen der Session:', error);
      res.json({ loggedIn: false });
    }
  });

  // Länderliste-Endpoint
  app.get('/api/countries', async (req, res) => {
    try {
      // Versuche zuerst, die CSV-Datei zu laden
      const csvPath = join(__dirname, '../docroot/countries.csv');
      let countries = {};
      
      try {
        const fileContent = readFileSync(csvPath, 'utf-8');
        const records = parse(fileContent, {
          columns: true,
          skip_empty_lines: true,
          quote: '"',
          trim: true,
          relax_quotes: true,
          relax_column_count: true
        });
        
        records.forEach(record => {
          if (record.Name && record.Code) {
            // Entferne alle Anführungszeichen (auch am Anfang/Ende)
            const name = record.Name.replace(/^["']+|["']+$/g, '').replace(/["']/g, '').trim();
            const code = record.Code.replace(/^["']+|["']+$/g, '').replace(/["']/g, '').trim();
            if (name && code) {
              countries[name] = code.toLowerCase();
            }
          }
        });
      } catch (fileError) {
        // Wenn die Datei nicht existiert, lade von der URL
        console.log('CSV-Datei nicht gefunden, lade von URL...');
        const response = await axios.get('https://pkgstore.datahub.io/core/country-list/data_csv/data/d7c9d7cfb42cb69f4422dec222dbbaa8/data_csv.csv');
        const lines = response.data.split('\n');
        
        for (let i = 1; i < lines.length; i++) {
          const line = lines[i].trim();
          if (!line) continue;
          
          // Parse CSV-Zeile mit Berücksichtigung von Anführungszeichen
          const parseCSVLine = (line) => {
            const result = [];
            let current = '';
            let inQuotes = false;
            
            for (let i = 0; i < line.length; i++) {
              const char = line[i];
              if (char === '"') {
                // Ignoriere Anführungszeichen, sie werden nicht zum Wert hinzugefügt
                inQuotes = !inQuotes;
              } else if (char === ',' && !inQuotes) {
                result.push(current.trim());
                current = '';
              } else {
                current += char;
              }
            }
            result.push(current.trim());
            return result;
          };
          
          const [name, code] = parseCSVLine(line);
          if (name && code) {
            // Entferne alle Anführungszeichen (auch am Anfang/Ende)
            const cleanName = name.replace(/^["']+|["']+$/g, '').replace(/["']/g, '').trim();
            const cleanCode = code.replace(/^["']+|["']+$/g, '').replace(/["']/g, '').trim();
            if (cleanName && cleanCode) {
              countries[cleanName] = cleanCode.toLowerCase();
            }
          }
        }
      }
      
      res.json(countries);
    } catch (error) {
      console.error('Fehler beim Laden der Länderliste:', error);
      res.status(500).json({ error: 'Fehler beim Laden der Länderliste' });
    }
  });

  // Partners-Links
  app.get('/api/partners', (req, res) => {
    try {
      const csvPath = join(__dirname, '../docroot/links.csv');
      const fileContent = readFileSync(csvPath, 'utf-8');
      const records = parse(fileContent, {
        columns: true,
        skip_empty_lines: true,
        quote: '"'
      });
      
      res.json(records);
    } catch (error) {
      console.error('Fehler beim Laden der Partner-Links:', error);
      res.status(500).json({ error: 'Fehler beim Laden der Partner-Links' });
    }
  });
}
