const express = require("express");
const pool = require("../db"); // Stelle sicher, dass dein DB-Pool importiert wird
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const nodemailer = require("nodemailer");
const { requireAuth, requireAdmin } = require("../middleware/auth"); // Falls Middleware in einer extra Datei liegt
const { transporter, sendActivationEmail } = require("../middleware/mail");

const router = express.Router();

// Registrierung
router.post("/register", async (req, res) => {
  const { username, email, password } = req.body;
  try {
    const hashedPassword = await bcrypt.hash(password, 10);
    await pool.query(
      "INSERT INTO users (username, email, password) VALUES ($1, $2, $3)",
      [username, email, hashedPassword]
    );
    const message =
      "Registrierung erfolgreich. Ein Admin wird dich in kürze freischalten";
    const mailOptions = {
      to: "admin@boergmann.it",
      from: "admin@boergmann.it",
      subject: "Neue Registrierung",
      text: `${username} hat sich registriert`,
    };

    transporter.sendMail(mailOptions, (error) => {
      if (error) {
        console.error("Error sending email:", error);
        res.status(500).json({ error: "Interner Serverfehler" });
      }
    });

    res.status(201).json({ message: message });
  } catch (error) {
    console.error("Error registering user:", error);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

// Login
router.post("/login", async (req, res) => {
  const { username, password } = req.body;

  try {
    const userResult = await pool.query(
      "SELECT *, CASE WHEN admin_temp IS NOT NULL AND (now() - admin_temp) > interval '22 hours' THEN 'expired' ELSE 'valid' END AS admin_status FROM users WHERE username = $1",
      [username]
    );
    if (userResult.rows.length > 0) {
      const user = userResult.rows[0];
      console.log(user);
      const match = await bcrypt.compare(password, user.password);
      if (match) {
        if (user.is_active) {
          const token = jwt.sign(
            { id: user.id, username: user.username, role: user.role },
            process.env.JWT_SECRET,
            {
              expiresIn: "24h",
            }
          );
          if (user.admin_status === "expired") {
            await pool.query(
              "UPDATE users SET role = $1, admin_temp = NULL WHERE id = $2",
              ["user", user.id]
            );
          }
          res.json({ token });
        } else {
          return res.status(401).json({ error: "Auf Freischlatung warten" });
        }
      } else {
        const message = "Falsches Passwort";
        return res.status(401).json({ error: "Ungültige Anmeldedaten" });
      }
    } else {
      const message = "Unbekannter Benutzer";
      return res.status(401).json({ error: "Ungültige Anmeldedaten" });
    }
  } catch (error) {
    console.error("Error logging in:", error);
    const message = "Error logging in:" + error;
    return res.status(401).json({ error: "Ungültige Anmeldedaten" });
  }
});

// Reset initiieren
router.post("/reset-password", async (req, res) => {
  const { email } = req.body;

  if (!email) {
    return res.status(400).json({ error: "E-Mail-Adresse ist erforderlich" });
  }

  try {
    // Prüfen, ob die E-Mail existiert
    const userResult = await pool.query(
      "SELECT id, username FROM users WHERE email = $1",
      [email]
    );

    if (userResult.rows.length === 0) {
      return res
        .status(404)
        .json({ error: "Benutzer mit dieser E-Mail nicht gefunden" });
    }

    const { id, username } = userResult.rows[0];

    // Token generieren (random 32 Byte)
    const token = crypto.randomBytes(32).toString("hex");
    const expires = new Date(Date.now() + 3600000); // Token 1 Stunde gültig

    // Token und Ablaufdatum in die DB speichern
    await pool.query(
      "UPDATE users SET reset_password_token = $1, reset_password_expires = $2 WHERE id = $3",
      [token, expires, id]
    );

    // Mail senden
    const resetLink = `https://${process.env.HOST}/reset/${token}`;
    const mailOptions = {
      from: process.env.MAILUSER,
      to: email,
      subject: "Passwort zurücksetzen",
      text: `Hallo ${username},\n\nKlicke auf den folgenden Link, um dein Passwort zurückzusetzen:\n\n${resetLink}\n\nDer Link ist 1 Stunde gültig.\n\nFalls du das Zurücksetzen nicht beantragt hast, ignoriere diese Nachricht.`,
    };

    await transporter.sendMail(mailOptions);

    res.json({ message: "Passwort-Reset-Link wurde per E-Mail gesendet." });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

// Reset Abschließen
router.post("/reset/:token", async (req, res) => {
  const { token } = req.params;
  const { password } = req.body;

  if (!password) {
    return res.status(400).json({ error: "Neues Passwort ist erforderlich" });
  }

  try {
    // Token in der Datenbank suchen und prüfen, ob es noch gültig ist
    const result = await pool.query(
      "SELECT id FROM users WHERE reset_password_token = $1 AND reset_password_expires > NOW()",
      [token]
    );

    if (result.rows.length === 0) {
      return res
        .status(400)
        .json({ error: "Ungültiges oder abgelaufenes Token" });
    }

    const userId = result.rows[0].id;

    // Passwort hashen
    const hashedPassword = await bcrypt.hash(password, 10);

    // Passwort speichern und Token-Felder leeren
    await pool.query(
      "UPDATE users SET password = $1, reset_password_token = NULL, reset_password_expires = NULL WHERE id = $2",
      [hashedPassword, userId]
    );

    res.json({ message: "Passwort erfolgreich zurückgesetzt" });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

// Email und/oder Passwort ändern
router.post("/update", requireAuth, async (req, res) => {
  const { email, password } = req.body;
  try {
    if (email) {
      await pool.query("UPDATE users SET email = $1 WHERE id = $2", [
        email,
        req.user.id,
      ]);
    }
    if (password) {
      const hashedPassword = await bcrypt.hash(password, 10);
      await pool.query("UPDATE users SET password = $1 WHERE id = $2", [
        hashedPassword,
        req.user.id,
      ]);
    }
    res.json({
      message: "Benutzerdaten erfolgreich aktualisiert",
    });
  } catch (error) {
    console.error("Error updating profile:", error);
    const message = "Error updating profile:" + error;
    res.status(400).json({ error: "Keine Änderungen vorgenommen" });
  }
});

// Liste der User mit Rollen und is_active
router.get("/admin", requireAuth, requireAdmin, async (req, res) => {
  try {
    const result = await pool.query(
      "SELECT id, username, email, role, is_active FROM users ORDER BY is_active ASC, role DESC"
    );
    res.json(result.rows);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

router.put("/activate/:id", requireAuth, requireAdmin, async (req, res) => {
  const { id } = req.params;

  try {
    // Benutzer-Daten abrufen (inklusive E-Mail und Benutzername)
    const userResult = await pool.query(
      "SELECT username, email FROM users WHERE id = $1",
      [id]
    );

    if (userResult.rows.length === 0) {
      return res.status(404).json({ error: "Benutzer nicht gefunden" });
    }

    const { username, email } = userResult.rows[0];

    // Benutzer aktivieren
    const result = await pool.query(
      "UPDATE users SET is_active = true WHERE id = $1 RETURNING id, username, is_active",
      [id]
    );

    if (result.rows.length === 0) {
      return res.status(404).json({ error: "Benutzer nicht gefunden" });
    }

    // E-Mail senden (wenn vorhanden)
    await sendActivationEmail(email, username);

    res.json({
      message: "Benutzer erfolgreich aktiviert",
      user: result.rows[0],
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

router.delete("/:id", requireAuth, requireAdmin, async (req, res) => {
  const { id } = req.params;

  try {
    // Prüfen, ob der Benutzer existiert
    const userResult = await pool.query(
      "SELECT id, username FROM users WHERE id = $1",
      [id]
    );

    if (userResult.rows.length === 0) {
      return res.status(404).json({ error: "Benutzer nicht gefunden" });
    }

    // Verhindern, dass sich Admins selbst löschen
    if (req.user.id == id) {
      return res
        .status(400)
        .json({ error: "Ein Admin kann sich nicht selbst löschen" });
    }

    // Benutzer löschen
    await pool.query("DELETE FROM users WHERE id = $1", [id]);

    res.json({
      message: "Benutzer erfolgreich gelöscht",
      user: userResult.rows[0],
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

// User zu Admins machen
router.put("/admin/:id", requireAuth, requireAdmin, async (req, res) => {
  const { id } = req.params;
  const { temporary } = req.body; // erwartet { "temporary": true } oder { "temporary": false }

  if (temporary === undefined) {
    return res.status(400).json({
      error: "Es muss angegeben werden, ob der Admin-Zugang temporär sein soll",
    });
  }

  try {
    let query, values;

    if (temporary) {
      query = `
                UPDATE users 
                SET role = 'admin', admin_temp = NOW() + INTERVAL '48 hours' 
                WHERE id = $1 RETURNING id, username, role, admin_temp
            `;
      values = [id];
    } else {
      query = `
                UPDATE users 
                SET role = 'admin', admin_temp = NULL 
                WHERE id = $1 RETURNING id, username, role, admin_temp
            `;
      values = [id];
    }

    const result = await pool.query(query, values);

    if (result.rows.length === 0) {
      return res.status(404).json({ error: "Benutzer nicht gefunden" });
    }

    res.json({
      message: "Benutzer wurde zum Admin gemacht",
      user: result.rows[0],
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

module.exports = router;