const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const Admin = require('../models/Admin');
const ResetToken = require('../models/ResetToken');
const config = require('../config/env');
const logger = require('../utils/logger');
const { auditAuth } = require('../middleware/auditLogger');

const login = async (req, res) => {
  try {
    const { username, password } = req.body;

    if (!username || !password) {
      return res.status(400).json({
        success: false,
        message: 'Benutzername und Passwort sind erforderlich'
      });
    }

    // Find admin (case-insensitive username match)
    const admin = await Admin.findOne({ username: { $regex: new RegExp(`^${username.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`, 'i') } });
    if (!admin) {
      await auditAuth(req, false, username, 'Benutzer nicht gefunden');
      return res.status(401).json({
        success: false,
        message: 'Benutzername oder Passwort falsch'
      });
    }

    // Check password
    const isPasswordValid = await admin.comparePassword(password);
    if (!isPasswordValid) {
      await auditAuth(req, false, username, 'Falsches Passwort');
      return res.status(401).json({
        success: false,
        message: 'Benutzername oder Passwort falsch'
      });
    }

    // Generate token
    const token = jwt.sign(
      { id: admin._id, username: admin.username },
      config.jwtSecret,
      { expiresIn: config.jwtExpiresIn }
    );

    // Set token in httpOnly cookie (XSS protection)
    res.cookie('token', token, {
      httpOnly: true,      // Not accessible via JavaScript (XSS protection)
      secure: false,       // Allow over HTTP in development (localhost)
      sameSite: 'lax',     // Relaxed CSRF protection (allows cross-port cookies on localhost)
      path: '/',           // Ensure cookie is sent for all app routes, including /nachsuche/api
      maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds
    });

    // Log successful login
    await auditAuth(req, true, username);

    res.json({
      success: true,
      user: {
        id: admin._id,
        username: admin.username
      }
    });
  } catch (error) {
    logger.error('Login-Fehler:', error);
    res.status(500).json({
      success: false,
      message: 'Serverfehler beim Anmelden'
    });
  }
};

const logout = async (req, res) => {
  try {
    // Log logout (get username from token if available)
    const username = req.user?.username || 'unknown';
    await auditAuth(req, true, username, null);
    
    // Clear the token cookie
    res.clearCookie('token', {
      httpOnly: true,
      secure: false,
      sameSite: 'lax',
      path: '/'
    });

    res.json({
      success: true,
      message: 'Erfolgreich abgemeldet'
    });
  } catch (error) {
    logger.error('Logout-Fehler:', error);
    res.status(500).json({
      success: false,
      message: 'Serverfehler beim Abmelden'
    });
  }
};

/**
 * Request password reset - generates reset token
 */
const forgotPassword = async (req, res) => {
  try {
    const { username } = req.body;

    if (!username) {
      return res.status(400).json({
        success: false,
        message: 'Benutzername ist erforderlich'
      });
    }

    // Find admin
    const admin = await Admin.findOne({ username });
    
    // Don't reveal if user exists (security best practice)
    if (!admin) {
      logger.warn(`Password reset requested for non-existent user: ${username}`);
      return res.json({
        success: true,
        message: 'Falls der Benutzer existiert, wurde ein Reset-Token generiert. Bitte kontaktieren Sie den Administrator.'
      });
    }

    // Generate secure random token
    const token = crypto.randomBytes(32).toString('hex');
    const expiresAt = new Date(Date.now() + 3600000); // 1 hour from now

    // Delete any existing tokens for this admin
    await ResetToken.deleteMany({ adminId: admin._id });

    // Create new reset token
    await ResetToken.create({
      adminId: admin._id,
      token,
      expiresAt
    });

    // In production, send email here
    // For development, log the token
    logger.info(`Password reset token for ${username}: ${token} (expires in 1 hour)`);
    
    res.json({
      success: true,
      message: 'Reset-Token wurde generiert. In der Entwicklungsumgebung finden Sie den Token in den Logs.',
      ...(config.nodeEnv === 'development' && { token }) // Only in dev!
    });
  } catch (error) {
    logger.error('Fehler bei Passwort-Reset-Anfrage:', error);
    res.status(500).json({
      success: false,
      message: 'Serverfehler bei Passwort-Reset-Anfrage'
    });
  }
};

/**
 * Reset password with token
 */
const resetPassword = async (req, res) => {
  try {
    const { token, newPassword } = req.body;

    if (!token || !newPassword) {
      return res.status(400).json({
        success: false,
        message: 'Token und neues Passwort sind erforderlich'
      });
    }

    // Validate password length
    if (newPassword.length < 6) {
      return res.status(400).json({
        success: false,
        message: 'Passwort muss mindestens 6 Zeichen lang sein'
      });
    }

    // Find valid, unused token
    const resetToken = await ResetToken.findOne({
      token,
      expiresAt: { $gt: new Date() },
      used: false
    });

    if (!resetToken) {
      return res.status(400).json({
        success: false,
        message: 'Ungültiger oder abgelaufener Reset-Token'
      });
    }

    // Update admin password
    const admin = await Admin.findById(resetToken.adminId);
    if (!admin) {
      return res.status(404).json({
        success: false,
        message: 'Admin nicht gefunden'
      });
    }

    admin.password = newPassword;
    await admin.save();

    // Mark token as used
    resetToken.used = true;
    await resetToken.save();

    // Delete all other tokens for this admin
    await ResetToken.deleteMany({ 
      adminId: admin._id,
      _id: { $ne: resetToken._id }
    });

    logger.info(`Password successfully reset for admin: ${admin.username}`);

    res.json({
      success: true,
      message: 'Passwort erfolgreich zurückgesetzt'
    });
  } catch (error) {
    logger.error('Fehler beim Zurücksetzen des Passworts:', error);
    res.status(500).json({
      success: false,
      message: 'Serverfehler beim Zurücksetzen des Passworts'
    });
  }
};

module.exports = { login, logout, forgotPassword, resetPassword };
