const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const crypto = require('crypto');
const User = require('../models/User');
const config = require('../config/env');
const logger = require('../utils/logger');

// POST /api/stoeberhundefuehrer/login  — email + password
const stoeberhundefuehrerLogin = async (req, res) => {
  try {
    const { email, password } = req.body;

    if (!email || !password) {
      return res.status(400).json({ success: false, message: 'E-Mail und Passwort erforderlich' });
    }

    const user = await User.findOne({ email: email.trim().toLowerCase(), deleted: false });
    if (!user || !user.passwordHash) {
      return res.status(401).json({ success: false, message: 'Ungültige Anmeldedaten oder kein Passwort hinterlegt' });
    }

    const valid = await bcrypt.compare(password, user.passwordHash);
    if (!valid) {
      return res.status(401).json({ success: false, message: 'Ungültige Anmeldedaten' });
    }

    const token = jwt.sign(
      { id: user._id.toString(), role: 'stoeberhundefuehrer' },
      config.jwtSecret,
      { expiresIn: '12h' }
    );

    res.json({
      success: true,
      token,
      user: {
        id: user._id,
        name: user.name,
        email: user.email,
        available: user.available,
        type: user.type,
        phone: user.phone,
        landline: user.landline,
        address: user.address
      }
    });
  } catch (error) {
    logger.error('Stöberhundeführer-Login Fehler:', error);
    res.status(500).json({ success: false, message: 'Serverfehler beim Login' });
  }
};

// POST /api/stoeberhundefuehrer/set-password  — set first password
// Admin first sets email, then the Stöberhundeführer can set their own password
const setStoeberhundefuehrerPassword = async (req, res) => {
  try {
    const { email, inviteToken, newPassword } = req.body;

    if (!email || !inviteToken || !newPassword || newPassword.length < 8) {
      return res.status(400).json({ success: false, message: 'E-Mail, Einladungs-Token und Passwort (min. 8 Zeichen) erforderlich' });
    }

    const user = await User.findOne({ email: email.trim().toLowerCase(), deleted: false })
      .select('+inviteToken +inviteTokenExpiry');

    // Always return the same error to prevent user enumeration
    const invalidMsg = 'Ungültiger oder abgelaufener Einladungs-Token';
    if (!user || !user.inviteToken || !user.inviteTokenExpiry) {
      return res.status(401).json({ success: false, message: invalidMsg });
    }

    if (user.inviteTokenExpiry < new Date()) {
      user.inviteToken = null;
      user.inviteTokenExpiry = null;
      await user.save();
      return res.status(401).json({ success: false, message: invalidMsg });
    }

    // Timing-safe comparison to prevent timing attacks
    const incoming = Buffer.from(inviteToken.trim());
    const stored   = Buffer.from(user.inviteToken);
    if (incoming.length !== stored.length || !crypto.timingSafeEqual(incoming, stored)) {
      return res.status(401).json({ success: false, message: invalidMsg });
    }

    user.passwordHash      = await bcrypt.hash(newPassword, 12);
    user.inviteToken       = null;
    user.inviteTokenExpiry = null;
    await user.save();

    res.json({ success: true, message: 'Passwort erfolgreich gesetzt' });
  } catch (error) {
    logger.error('Passwort setzen Fehler:', error);
    res.status(500).json({ success: false, message: 'Serverfehler' });
  }
};

// PUT /api/stoeberhundefuehrer/me  — Stöberhundeführer updates own availability + contact data
const updateStoeberhundefuehrerSelf = async (req, res) => {
  try {
    const userId = req.stoeberhundefuehrerUser.id;
    const { available, phone, landline, address } = req.body;

    const update = {};
    if (typeof available === 'boolean') update.available = available;
    if (phone && phone.trim()) update.phone = phone.trim();
    if (landline !== undefined) update.landline = landline ? landline.trim() : null;
    if (address && address.trim()) update.address = address.trim();

    const user = await User.findByIdAndUpdate(
      userId,
      update,
      { new: true, select: '-passwordHash' }
    );

    if (!user) {
      return res.status(404).json({ success: false, message: 'Stöberhundeführer nicht gefunden' });
    }

    res.json({ success: true, data: user });
  } catch (error) {
    logger.error('Stöberhundeführer-Update Fehler:', error);
    res.status(500).json({ success: false, message: 'Fehler beim Aktualisieren' });
  }
};

// GET /api/stoeberhundefuehrer/me — get own profile
const getStoeberhundefuehrerSelf = async (req, res) => {
  try {
    const user = await User.findById(req.stoeberhundefuehrerUser.id).select('-passwordHash');
    if (!user) return res.status(404).json({ success: false, message: 'Nicht gefunden' });
    res.json({ success: true, data: user });
  } catch (error) {
    res.status(500).json({ success: false, message: 'Serverfehler' });
  }
};

// POST /api/stoeberhundefuehrer/:id/invite-token — Admin generates one-time invite token
const generateInviteToken = async (req, res) => {
  try {
    const user = await User.findOne({ _id: req.params.id, deleted: false })
      .select('+inviteToken +inviteTokenExpiry');
    if (!user) {
      return res.status(404).json({ success: false, message: 'Benutzer nicht gefunden' });
    }
    if (!user.email) {
      return res.status(400).json({ success: false, message: 'Kein E-Mail für diesen Benutzer hinterlegt' });
    }

    const token = crypto.randomBytes(32).toString('hex');
    user.inviteToken       = token;
    user.inviteTokenExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); // 7 days
    await user.save();

    res.json({
      success: true,
      message: 'Einladungs-Token generiert (gültig 7 Tage)',
      data: { inviteToken: token, expiresAt: user.inviteTokenExpiry, email: user.email }
    });
  } catch (error) {
    logger.error('Fehler beim Generieren des Einladungs-Tokens:', error);
    res.status(500).json({ success: false, message: 'Serverfehler' });
  }
};

module.exports = { stoeberhundefuehrerLogin, setStoeberhundefuehrerPassword, generateInviteToken, updateStoeberhundefuehrerSelf, getStoeberhundefuehrerSelf };
