import jwt from "jsonwebtoken";
import Admin from "../models/Admin.js";
import logger from "../utils/logger.js";

/**
 * Authentication Middleware
 * Verifies JWT token and attaches admin to request
 * Returns 401 if token is missing or invalid
 */
export const authenticate = async (req, res, next) => {
  try {
    let token;

    // Get token from header
    if (
      req.headers.authorization &&
      req.headers.authorization.startsWith("Bearer")
    ) {
      token = req.headers.authorization.split(" ")[1];
    }

    // Check if token exists
    if (!token) {
      return res.status(401).json({
        success: false,
        error: "Not authorized to access this route",
      });
    }

    try {
      // Verify token
      const decoded = jwt.verify(token, process.env.JWT_SECRET);

      // Get admin from token
      const admin = await Admin.findById(decoded.id);

      if (!admin) {
        return res.status(401).json({
          success: false,
          error: "Admin not found",
        });
      }

      // Check if admin is active
      if (!admin.isActive) {
        return res.status(403).json({
          success: false,
          error: "Your account has been deactivated",
        });
      }

      // Attach admin to request
      req.admin = admin;
      next();
    } catch (error) {
      if (error.name === "JsonWebTokenError") {
        return res.status(401).json({
          success: false,
          error: "Invalid token",
        });
      }

      if (error.name === "TokenExpiredError") {
        return res.status(401).json({
          success: false,
          error: "Token expired",
        });
      }

      throw error;
    }
  } catch (error) {
    logger.error("Authentication error", error);
    next(error);
  }
};

/**
 * Optional Authentication Middleware
 * Tries to authenticate but doesn't fail if token is missing
 * Attaches admin to request if authenticated, otherwise req.admin is undefined
 */
export const optionalAuthenticate = async (req, res, next) => {
  try {
    let token;

    // Get token from header
    if (
      req.headers.authorization &&
      req.headers.authorization.startsWith("Bearer")
    ) {
      token = req.headers.authorization.split(" ")[1];
    }

    // If no token, continue without authentication
    if (!token) {
      req.admin = undefined;
      return next();
    }

    try {
      // Verify token
      const decoded = jwt.verify(token, process.env.JWT_SECRET);

      // Get admin from token
      const admin = await Admin.findById(decoded.id);

      if (admin && admin.isActive) {
        // Attach admin to request
        req.admin = admin;
      } else {
        req.admin = undefined;
      }
    } catch (error) {
      // If token is invalid, continue without authentication
      req.admin = undefined;
    }

    next();
  } catch (error) {
    // On any error, continue without authentication
    req.admin = undefined;
    next();
  }
};

/**
 * Single Admin Authorization Middleware
 * Ensures only the allowed admin can access protected routes
 */
export const authorize = async (req, res, next) => {
  try {
    if (!req.admin) {
      return res.status(401).json({
        success: false,
        error: "Not authorized to access this route",
      });
    }

    // Get allowed admin email from environment
    const allowedAdminEmail = process.env.ADMIN_EMAIL || "admin@samaa.com";

    // Check if the authenticated admin is the allowed admin
    if (req.admin.email.toLowerCase() !== allowedAdminEmail.toLowerCase()) {
      logger.warn("Unauthorized access attempt", {
        email: req.admin.email,
        allowedEmail: allowedAdminEmail,
      });

      return res.status(403).json({
        success: false,
        error: "Access denied. Only the authorized admin can access this route",
      });
    }

    next();
  } catch (error) {
    logger.error("Authorization error", error);
    next(error);
  }
};
