const express = require("express");
const bcrypt = require("bcrypt");
const { query } = require("../config/database");
const logger = require("../config/logger");
const {
  validators,
  handleValidationErrors,
} = require("../middleware/validators");
const { asyncHandler } = require("../middleware/errorHandler");
const {
  sendSuccess,
  sendError,
  sendUnauthorized,
} = require("../utils/responseHelpers");
const { HTTP_STATUS } = require("../config/constants");
const {
  recordFailedAttempt,
  resetFailedAttempts,
  checkBlocked,
} = require("../middleware/bruteForceProtection");
const router = express.Router();

const getUserByEmailOrUsername = async (emailOrUsername) => {
  const result = await query(
    `SELECT u.id, u.email, u.username, u.passwordhash, u.role_id, u.isactive,
            r.name as role_name, r.permissions
     FROM adminusers u
     LEFT JOIN roles r ON u.role_id = r.id
     WHERE u.email = $1 OR u.username = $1`,
    [emailOrUsername],
  );
  return result.rows[0] || null;
};

const updateLastLogin = async (userId) => {
  await query("UPDATE adminusers SET last_login = NOW() WHERE id = $1", [
    userId,
  ]);
};

const createUserSession = (req, user) => {
  req.session.user = {
    id: user.id,
    email: user.email,
    username: user.username,
    role_id: user.role_id,
    role_name: user.role_name,
    permissions: user.permissions,
  };
};

// Login endpoint
router.post(
  "/login",
  checkBlocked,
  validators.login,
  handleValidationErrors,
  asyncHandler(async (req, res) => {
    const { email, password } = req.body;
    const ip = req.ip || req.connection.remoteAddress;
    const admin = await getUserByEmailOrUsername(email);

    if (!admin) {
      logger.warn("Login attempt with invalid email/username", { email, ip });
      recordFailedAttempt(ip);
      return sendUnauthorized(res, "Invalid email or password");
    }

    if (!admin.isactive) {
      logger.warn("Login attempt with deactivated account", { email, ip });
      recordFailedAttempt(ip);
      return sendUnauthorized(res, "Account is deactivated");
    }

    const validPassword = await bcrypt.compare(password, admin.passwordhash);
    if (!validPassword) {
      logger.warn("Login attempt with invalid password", { email, ip });
      recordFailedAttempt(ip);
      return sendUnauthorized(res, "Invalid email or password");
    }

    // Reset failed attempts on successful login
    resetFailedAttempts(ip);

    await updateLastLogin(admin.id);
    createUserSession(req, admin);

    req.session.save((err) => {
      if (err) {
        logger.error("Session save error:", err);
        return sendError(res, "Session error");
      }

      logger.info("User logged in successfully", {
        userId: admin.id,
        email: admin.email,
        ip,
      });
      sendSuccess(res, { user: req.session.user });
    });
  }),
);

// Check session endpoint
router.get("/session", (req, res) => {
  if (req.session?.user) {
    return sendSuccess(res, { authenticated: true, user: req.session.user });
  }
  res.status(HTTP_STATUS.UNAUTHORIZED).json({ authenticated: false });
});

// Logout endpoint
router.post("/logout", (req, res) => {
  const userId = req.session?.user?.id;

  req.session.destroy((err) => {
    if (err) {
      logger.error("Logout error:", err);
      return sendError(res, "Logout failed");
    }

    logger.info("User logged out", { userId });
    sendSuccess(res, { message: "Logged out successfully" });
  });
});

module.exports = router;
