/**
 * TASKMATE - Admin Routes
 * =======================
 * API-Endpunkte für Benutzerverwaltung
 */

const express = require('express');
const bcrypt = require('bcryptjs');
const router = express.Router();
const { getDb } = require('../database');
const { authenticateToken, requireAdmin } = require('../middleware/auth');
const logger = require('../utils/logger');

/**
 * Standard-Upload-Einstellungen
 */
const DEFAULT_UPLOAD_SETTINGS = {
  maxFileSizeMB: 15,
  allowedTypes: {
    images: {
      enabled: true,
      types: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']
    },
    documents: {
      enabled: true,
      types: ['application/pdf']
    },
    office: {
      enabled: true,
      types: [
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation'
      ]
    },
    text: {
      enabled: true,
      types: ['text/plain', 'text/csv', 'text/markdown']
    },
    archives: {
      enabled: true,
      types: ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed']
    },
    data: {
      enabled: true,
      types: ['application/json']
    }
  }
};

// Alle Admin-Routes erfordern Authentifizierung und Admin-Rolle
router.use(authenticateToken);
router.use(requireAdmin);

/**
 * GET /api/admin/users - Alle Benutzer abrufen
 */
router.get('/users', (req, res) => {
  try {
    const db = getDb();
    const users = db.prepare(`
      SELECT id, username, display_name, color, role, permissions, email,
             created_at, last_login, failed_attempts, locked_until
      FROM users
      ORDER BY id
    `).all();

    // Permissions parsen
    const parsedUsers = users.map(user => ({
      ...user,
      permissions: JSON.parse(user.permissions || '[]')
    }));

    res.json(parsedUsers);
  } catch (error) {
    logger.error('Fehler beim Abrufen der Benutzer:', error);
    res.status(500).json({ error: 'Fehler beim Abrufen der Benutzer' });
  }
});

/**
 * POST /api/admin/users - Neuen Benutzer anlegen
 */
router.post('/users', async (req, res) => {
  try {
    const { username, password, displayName, email, role, permissions } = req.body;

    // Validierung
    if (!username || !password || !displayName || !email) {
      return res.status(400).json({ error: 'Kürzel, Passwort, Anzeigename und E-Mail erforderlich' });
    }

    // E-Mail-Validierung
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(email)) {
      return res.status(400).json({ error: 'Ungültige E-Mail-Adresse' });
    }

    // Kürzel muss genau 2 Buchstaben sein
    const usernameUpper = username.toUpperCase();
    if (!/^[A-Z]{2}$/.test(usernameUpper)) {
      return res.status(400).json({ error: 'Kürzel muss genau 2 Buchstaben sein (z.B. HG)' });
    }

    if (password.length < 8) {
      return res.status(400).json({ error: 'Passwort muss mindestens 8 Zeichen haben' });
    }

    const db = getDb();

    // Prüfen ob Kürzel bereits existiert
    const existing = db.prepare('SELECT id FROM users WHERE username = ?').get(usernameUpper);
    if (existing) {
      return res.status(400).json({ error: 'Kürzel bereits vergeben' });
    }

    // Prüfen ob E-Mail bereits existiert
    const existingEmail = db.prepare('SELECT id FROM users WHERE email = ?').get(email.toLowerCase());
    if (existingEmail) {
      return res.status(400).json({ error: 'E-Mail bereits vergeben' });
    }

    // Passwort hashen
    const passwordHash = await bcrypt.hash(password, 12);

    // Standardfarbe Grau
    const defaultColor = '#808080';

    // Benutzer erstellen
    const result = db.prepare(`
      INSERT INTO users (username, password_hash, display_name, color, role, permissions, email)
      VALUES (?, ?, ?, ?, ?, ?, ?)
    `).run(
      usernameUpper,
      passwordHash,
      displayName,
      defaultColor,
      role || 'user',
      JSON.stringify(permissions || []),
      email.toLowerCase()
    );

    logger.info(`Admin ${req.user.username} hat Benutzer ${usernameUpper} erstellt`);

    res.status(201).json({
      id: result.lastInsertRowid,
      username: usernameUpper,
      displayName,
      email: email.toLowerCase(),
      color: defaultColor,
      role: role || 'user',
      permissions: permissions || []
    });
  } catch (error) {
    logger.error('Fehler beim Erstellen des Benutzers:', error);
    res.status(500).json({ error: 'Fehler beim Erstellen des Benutzers' });
  }
});

/**
 * PUT /api/admin/users/:id - Benutzer bearbeiten
 */
router.put('/users/:id', async (req, res) => {
  try {
    const userId = parseInt(req.params.id);
    const { displayName, color, role, permissions, password, unlockAccount, email } = req.body;

    const db = getDb();

    // Benutzer prüfen
    const user = db.prepare('SELECT * FROM users WHERE id = ?').get(userId);
    if (!user) {
      return res.status(404).json({ error: 'Benutzer nicht gefunden' });
    }

    // Verhindern, dass der einzige Admin seine Rolle ändert
    if (user.role === 'admin' && role !== 'admin') {
      const adminCount = db.prepare("SELECT COUNT(*) as count FROM users WHERE role = 'admin'").get();
      if (adminCount.count <= 1) {
        return res.status(400).json({ error: 'Mindestens ein Admin muss existieren' });
      }
    }

    // Update-Felder sammeln
    const updates = [];
    const params = [];

    if (displayName !== undefined) {
      updates.push('display_name = ?');
      params.push(displayName);
    }

    if (color !== undefined) {
      updates.push('color = ?');
      params.push(color);
    }

    if (role !== undefined) {
      updates.push('role = ?');
      params.push(role);
    }

    if (permissions !== undefined) {
      updates.push('permissions = ?');
      params.push(JSON.stringify(permissions));
    }

    if (password) {
      if (password.length < 8) {
        return res.status(400).json({ error: 'Passwort muss mindestens 8 Zeichen haben' });
      }
      const passwordHash = await bcrypt.hash(password, 12);
      updates.push('password_hash = ?');
      params.push(passwordHash);
    }

    if (unlockAccount) {
      updates.push('failed_attempts = 0');
      updates.push('locked_until = NULL');
    }

    if (email !== undefined) {
      // E-Mail-Validierung
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!emailRegex.test(email)) {
        return res.status(400).json({ error: 'Ungültige E-Mail-Adresse' });
      }
      // Prüfen ob E-Mail bereits von anderem Benutzer verwendet wird
      const existingEmail = db.prepare('SELECT id FROM users WHERE email = ? AND id != ?').get(email.toLowerCase(), userId);
      if (existingEmail) {
        return res.status(400).json({ error: 'E-Mail bereits vergeben' });
      }
      updates.push('email = ?');
      params.push(email.toLowerCase());
    }

    if (updates.length === 0) {
      return res.status(400).json({ error: 'Keine Änderungen angegeben' });
    }

    params.push(userId);
    db.prepare(`UPDATE users SET ${updates.join(', ')} WHERE id = ?`).run(...params);

    logger.info(`Admin ${req.user.username} hat Benutzer ${user.username} bearbeitet`);

    // Aktualisierten Benutzer zurueckgeben
    const updatedUser = db.prepare(`
      SELECT id, username, display_name, color, role, permissions, email,
             created_at, last_login, failed_attempts, locked_until
      FROM users WHERE id = ?
    `).get(userId);

    res.json({
      ...updatedUser,
      permissions: JSON.parse(updatedUser.permissions || '[]')
    });
  } catch (error) {
    logger.error('Fehler beim Bearbeiten des Benutzers:', error);
    res.status(500).json({ error: 'Fehler beim Bearbeiten des Benutzers' });
  }
});

/**
 * DELETE /api/admin/users/:id - Benutzer löschen
 */
router.delete('/users/:id', (req, res) => {
  try {
    const userId = parseInt(req.params.id);
    const db = getDb();

    // Benutzer prüfen
    const user = db.prepare('SELECT * FROM users WHERE id = ?').get(userId);
    if (!user) {
      return res.status(404).json({ error: 'Benutzer nicht gefunden' });
    }

    // Verhindern, dass der letzte Admin gelöscht wird
    if (user.role === 'admin') {
      const adminCount = db.prepare("SELECT COUNT(*) as count FROM users WHERE role = 'admin'").get();
      if (adminCount.count <= 1) {
        return res.status(400).json({ error: 'Der letzte Admin kann nicht gelöscht werden' });
      }
    }

    // Verhindern, dass man sich selbst löscht
    if (userId === req.user.id) {
      return res.status(400).json({ error: 'Sie können sich nicht selbst löschen' });
    }

    // Alle Referenzen auf den Benutzer auf NULL setzen oder löschen
    // Tasks
    db.prepare('UPDATE tasks SET assigned_to = NULL WHERE assigned_to = ?').run(userId);
    db.prepare('UPDATE tasks SET created_by = NULL WHERE created_by = ?').run(userId);

    // Kommentare
    db.prepare('UPDATE comments SET user_id = NULL WHERE user_id = ?').run(userId);

    // Historie
    db.prepare('UPDATE history SET user_id = NULL WHERE user_id = ?').run(userId);

    // Vorschläge
    db.prepare('UPDATE proposals SET created_by = NULL WHERE created_by = ?').run(userId);
    db.prepare('UPDATE proposals SET approved_by = NULL WHERE approved_by = ?').run(userId);

    // Projekte
    db.prepare('UPDATE projects SET created_by = NULL WHERE created_by = ?').run(userId);

    // Anhänge
    db.prepare('UPDATE attachments SET uploaded_by = NULL WHERE uploaded_by = ?').run(userId);

    // Links
    db.prepare('UPDATE links SET created_by = NULL WHERE created_by = ?').run(userId);

    // Login-Audit (kann gelöscht werden)
    db.prepare('DELETE FROM login_audit WHERE user_id = ?').run(userId);

    // Votes des Benutzers löschen
    db.prepare('DELETE FROM proposal_votes WHERE user_id = ?').run(userId);

    // Benutzer löschen
    db.prepare('DELETE FROM users WHERE id = ?').run(userId);

    logger.info(`Admin ${req.user.username} hat Benutzer ${user.username} gelöscht`);

    res.json({ success: true });
  } catch (error) {
    logger.error('Fehler beim Löschen des Benutzers:', error);
    res.status(500).json({ error: 'Fehler beim Löschen des Benutzers' });
  }
});

/**
 * GET /api/admin/upload-settings - Upload-Einstellungen abrufen
 */
router.get('/upload-settings', (req, res) => {
  try {
    const db = getDb();
    const setting = db.prepare('SELECT value FROM settings WHERE key = ?').get('upload_settings');

    if (setting) {
      const settings = JSON.parse(setting.value);
      res.json(settings);
    } else {
      // Standard-Einstellungen zurückgeben und speichern
      db.prepare('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)')
        .run('upload_settings', JSON.stringify(DEFAULT_UPLOAD_SETTINGS));
      res.json(DEFAULT_UPLOAD_SETTINGS);
    }
  } catch (error) {
    logger.error('Fehler beim Abrufen der Upload-Einstellungen:', error);
    res.status(500).json({ error: 'Fehler beim Abrufen der Upload-Einstellungen' });
  }
});

/**
 * PUT /api/admin/upload-settings - Upload-Einstellungen speichern
 */
router.put('/upload-settings', (req, res) => {
  try {
    const { maxFileSizeMB, allowedTypes } = req.body;

    // Validierung
    if (typeof maxFileSizeMB !== 'number' || maxFileSizeMB < 1 || maxFileSizeMB > 100) {
      return res.status(400).json({ error: 'Maximale Dateigröße muss zwischen 1 und 100 MB liegen' });
    }

    if (!allowedTypes || typeof allowedTypes !== 'object') {
      return res.status(400).json({ error: 'Ungültige Dateityp-Konfiguration' });
    }

    const settings = { maxFileSizeMB, allowedTypes };

    const db = getDb();
    db.prepare('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)')
      .run('upload_settings', JSON.stringify(settings));

    logger.info(`Admin ${req.user.username} hat Upload-Einstellungen geändert`);

    res.json(settings);
  } catch (error) {
    logger.error('Fehler beim Speichern der Upload-Einstellungen:', error);
    res.status(500).json({ error: 'Fehler beim Speichern der Upload-Einstellungen' });
  }
});

/**
 * Hilfsfunktion zum Abrufen der aktuellen Upload-Einstellungen
 */
function getUploadSettings() {
  try {
    const db = getDb();
    const setting = db.prepare('SELECT value FROM settings WHERE key = ?').get('upload_settings');

    if (setting) {
      return JSON.parse(setting.value);
    }
    return DEFAULT_UPLOAD_SETTINGS;
  } catch (error) {
    logger.error('Fehler beim Abrufen der Upload-Einstellungen:', error);
    return DEFAULT_UPLOAD_SETTINGS;
  }
}

module.exports = router;
module.exports.getUploadSettings = getUploadSettings;
module.exports.DEFAULT_UPLOAD_SETTINGS = DEFAULT_UPLOAD_SETTINGS;
