/**
 * TASKMATE - Hauptserver
 * ======================
 * Node.js/Express Backend mit Socket.io für Echtzeit-Sync
 */

// Umgebungsvariablen laden (muss ganz oben stehen!)
require('dotenv').config();

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const path = require('path');
const helmet = require('helmet');
const cors = require('cors');
const cookieParser = require('cookie-parser');

// Lokale Module
const database = require('./database');
const logger = require('./utils/logger');
const backup = require('./utils/backup');
const { authenticateToken, authenticateSocket } = require('./middleware/auth');
const csrfProtection = require('./middleware/csrf');

// Routes
const authRoutes = require('./routes/auth');
const projectRoutes = require('./routes/projects');
const columnRoutes = require('./routes/columns');
const taskRoutes = require('./routes/tasks');
const subtaskRoutes = require('./routes/subtasks');
const commentRoutes = require('./routes/comments');
const labelRoutes = require('./routes/labels');
const fileRoutes = require('./routes/files');
const linkRoutes = require('./routes/links');
const templateRoutes = require('./routes/templates');
const statsRoutes = require('./routes/stats');
const exportRoutes = require('./routes/export');
const importRoutes = require('./routes/import');
const healthRoutes = require('./routes/health');
const adminRoutes = require('./routes/admin');
const proposalRoutes = require('./routes/proposals');
const notificationRoutes = require('./routes/notifications');
const notificationService = require('./services/notificationService');
const reminderService = require('./services/reminderService');
const gitRoutes = require('./routes/git');
const applicationsRoutes = require('./routes/applications');
const giteaRoutes = require('./routes/gitea');
const knowledgeRoutes = require('./routes/knowledge');
const codingRoutes = require('./routes/coding');
const reminderRoutes = require('./routes/reminders');

// Express App erstellen
const app = express();
const server = http.createServer(app);

// Socket.io Setup
const io = new Server(server, {
  cors: {
    origin: true,
    credentials: true
  }
});

// =============================================================================
// MIDDLEWARE
// =============================================================================

// Erweiterte Sicherheits-Header (CSP temporär deaktiviert für Login-Fix)
app.use(helmet({
  contentSecurityPolicy: false, // Temporär deaktiviert
  hsts: {
    maxAge: 31536000, // 1 Jahr
    includeSubDomains: true,
    preload: true
  },
  noSniff: true,
  xssFilter: true,
  referrerPolicy: {
    policy: "strict-origin-when-cross-origin"
  }
}));

// CORS
app.use(cors({
  origin: process.env.CORS_ORIGIN || 'https://taskmate.aegis-sight.de',
  credentials: true
}));

// Body Parser
app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ extended: true, limit: '1mb' }));

// Cookie Parser
app.use(cookieParser());

// Input Sanitization (vor allen anderen Middlewares)
const { sanitizeMiddleware } = require('./middleware/validation');
app.use(sanitizeMiddleware);

// Request Logging (nur API-Requests, keine statischen Assets)
app.use((req, res, next) => {
  if (req.originalUrl.startsWith('/api/')) {
    const start = Date.now();
    res.on('finish', () => {
      const duration = Date.now() - start;
      logger.info(`${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms`);
    });
  }
  next();
});

// Statische Dateien (Frontend) - ohne Caching für Development
app.use(express.static(path.join(__dirname, 'public'), {
  etag: false,
  lastModified: false,
  cacheControl: false,
  setHeaders: (res, path) => {
    res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');
  }
}));

// Uploads-Ordner
app.use('/uploads', authenticateToken, express.static(process.env.UPLOAD_DIR || path.join(__dirname, 'uploads')));

// =============================================================================
// API ROUTES
// =============================================================================

// Health Check (ohne Auth)
app.use('/api/health', healthRoutes);

// Auth Routes (Login/Logout - teilweise ohne Auth)
app.use('/api/auth', authRoutes);

// Geschützte Routes
app.use('/api/projects', authenticateToken, csrfProtection, projectRoutes);
app.use('/api/columns', authenticateToken, csrfProtection, columnRoutes);
app.use('/api/tasks', authenticateToken, csrfProtection, taskRoutes);
app.use('/api/subtasks', authenticateToken, csrfProtection, subtaskRoutes);
app.use('/api/comments', authenticateToken, csrfProtection, commentRoutes);
app.use('/api/labels', authenticateToken, csrfProtection, labelRoutes);
app.use('/api/files', authenticateToken, csrfProtection, fileRoutes);
app.use('/api/links', authenticateToken, csrfProtection, linkRoutes);
app.use('/api/templates', authenticateToken, csrfProtection, templateRoutes);
app.use('/api/stats', authenticateToken, csrfProtection, statsRoutes);
app.use('/api/export', authenticateToken, csrfProtection, exportRoutes);
app.use('/api/import', authenticateToken, csrfProtection, importRoutes);

// Admin-Routes
app.use('/api/admin', authenticateToken, csrfProtection, adminRoutes);

// Proposals-Routes
app.use('/api/proposals', authenticateToken, csrfProtection, proposalRoutes);

// Notifications-Routes
app.use('/api/notifications', authenticateToken, csrfProtection, notificationRoutes);

// Git-Routes (lokale Git-Operationen)
app.use('/api/git', authenticateToken, csrfProtection, gitRoutes);

// Applications-Routes (Projekt-Repository-Verknüpfung)
app.use('/api/applications', authenticateToken, csrfProtection, applicationsRoutes);

// Gitea-Routes (Gitea API Integration)
app.use('/api/gitea', authenticateToken, csrfProtection, giteaRoutes);

// Knowledge-Routes (Wissensmanagement)
app.use('/api/knowledge', authenticateToken, csrfProtection, knowledgeRoutes);

// Coding-Routes (Entwicklungsverzeichnisse mit Claude/Codex)
app.use('/api/coding', authenticateToken, csrfProtection, codingRoutes);

// Reminder-Routes (Erinnerungen)
app.use('/api/reminders', authenticateToken, csrfProtection, reminderRoutes);

// Contacts-Routes (Kontakte)
app.use('/api/contacts', authenticateToken, csrfProtection, require('./routes/contacts'));

// =============================================================================
// SOCKET.IO
// =============================================================================

// Socket.io Middleware für Authentifizierung
io.use(authenticateSocket);

// Verbundene Clients speichern
const connectedClients = new Map();

io.on('connection', (socket) => {
  const userId = socket.user.id;
  const username = socket.user.username;

  logger.info(`Socket connected: ${username} (${socket.id})`);

  // Client registrieren
  connectedClients.set(socket.id, {
    userId,
    username,
    connectedAt: new Date()
  });

  // User-spezifischen Raum beitreten (für Benachrichtigungen)
  socket.join(`user:${userId}`);

  // Allen mitteilen, dass jemand online ist
  io.emit('user:online', {
    userId,
    username,
    onlineUsers: Array.from(connectedClients.values()).map(c => ({
      userId: c.userId,
      username: c.username
    }))
  });

  // Projekt-Raum beitreten
  socket.on('project:join', (projectId) => {
    socket.join(`project:${projectId}`);
    logger.info(`${username} joined project:${projectId}`);
  });

  // Projekt-Raum verlassen
  socket.on('project:leave', (projectId) => {
    socket.leave(`project:${projectId}`);
    logger.info(`${username} left project:${projectId}`);
  });

  // Disconnect
  socket.on('disconnect', () => {
    logger.info(`Socket disconnected: ${username} (${socket.id})`);
    connectedClients.delete(socket.id);

    // Allen mitteilen, dass jemand offline ist
    io.emit('user:offline', {
      userId,
      username,
      onlineUsers: Array.from(connectedClients.values()).map(c => ({
        userId: c.userId,
        username: c.username
      }))
    });
  });
});

// Socket.io Instance global verfügbar machen für Routes
app.set('io', io);

// =============================================================================
// FEHLERBEHANDLUNG
// =============================================================================

// 404 Handler
app.use((req, res, next) => {
  // API-Anfragen: JSON-Fehler
  if (req.path.startsWith('/api/')) {
    return res.status(404).json({ error: 'Endpoint nicht gefunden' });
  }
  // Andere Anfragen: index.html (SPA)
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// Globaler Error Handler
app.use((err, req, res, next) => {
  logger.error(`Error: ${err.message}`, { stack: err.stack });

  // CSRF-Fehler
  if (err.code === 'CSRF_ERROR') {
    return res.status(403).json({ error: 'Ungültiges CSRF-Token' });
  }

  // Multer-Fehler (Datei-Upload)
  if (err.code === 'LIMIT_FILE_SIZE') {
    return res.status(413).json({
      error: `Datei zu groß. Maximum: ${process.env.MAX_FILE_SIZE_MB || 15} MB`
    });
  }

  // Allgemeiner Fehler
  res.status(err.status || 500).json({
    error: process.env.NODE_ENV === 'production'
      ? 'Ein Fehler ist aufgetreten'
      : err.message
  });
});

// =============================================================================
// SERVER STARTEN
// =============================================================================

const PORT = process.env.PORT || 3000;

// Datenbank initialisieren
database.initialize()
  .then(() => {
    // Server starten
    server.listen(PORT, () => {
      logger.info(`Server läuft auf Port ${PORT}`);
      logger.info(`Umgebung: ${process.env.NODE_ENV || 'development'}`);

      // Backup-System starten
      if (process.env.BACKUP_ENABLED !== 'false') {
        backup.startScheduler();
        logger.info('Automatische Backups aktiviert');
      }

      // Fälligkeits-Benachrichtigungen Scheduler (alle 6 Stunden)
      setInterval(() => {
        notificationService.checkDueTasks(io);
      }, 6 * 60 * 60 * 1000);

      // Erste Prüfung nach 1 Minute
      setTimeout(() => {
        notificationService.checkDueTasks(io);
        logger.info('Fälligkeits-Check für Benachrichtigungen gestartet');
      }, 60 * 1000);

      // Reminder Service starten
      const reminderServiceInstance = reminderService.getInstance(io);
      reminderServiceInstance.start();
    });
  })
  .catch((err) => {
    logger.error('Fehler beim Starten:', err);
    process.exit(1);
  });

// Graceful Shutdown
process.on('SIGTERM', () => {
  logger.info('SIGTERM empfangen, fahre herunter...');

  // Reminder Service stoppen
  const reminderServiceInstance = reminderService.getInstance();
  reminderServiceInstance.stop();

  server.close(() => {
    database.close();
    logger.info('Server beendet');
    process.exit(0);
  });
});

process.on('SIGINT', () => {
  logger.info('SIGINT empfangen, fahre herunter...');

  // Reminder Service stoppen
  const reminderServiceInstance = reminderService.getInstance();
  reminderServiceInstance.stop();

  server.close(() => {
    database.close();
    logger.info('Server beendet');
    process.exit(0);
  });
});
