import { UniqueID } from "@/core/common/domain";
import { ApiError, ExpressController } from "@/core/common/presentation";
//import { authProvider } from "@/contexts/auth/infraestructure";
import { NextFunction, Response } from "express";
import { authProvider } from "../../../../../../../modules/auth/src/api/lib/passport";
import { AuthenticatedUser } from "../../domain";
import { AuthenticatedRequest } from "../express/types";

// Comprueba el rol del usuario
const _authorizeUser = (condition: (user: AuthenticatedUser) => boolean) => {
  return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    const user = req.user as AuthenticatedUser;

    if (!user || !condition(user)) {
      return ExpressController.errorResponse(
        new ApiError({
          status: 401,
          title: "Unauthorized",
          detail: "You are not authorized to access this resource.",
        }),
        res
      );
    }

    return next();
  };
};

// Verifica que el usuario esté autenticado
export const checkUser = [
  authProvider.authenticateJWT(),
  _authorizeUser((user) => true /*user.isUser*/),
];

// Verifica que el usuario sea administrador
export const checkUserIsAdmin = [
  authProvider.authenticateJWT(),
  _authorizeUser((user) => true /*user.isAdmin*/),
];

// Middleware para verificar que el usuario sea administrador o el dueño de los datos (self)
export const checkUserIsAdminOrOwner = [
  (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    const user = req.user as AuthenticatedUser;
    const { userId } = req.params;

    // Si el usuario es admin, está autorizado
    if (user.isAdmin) {
      return next();
    }

    // Si el usuario es sí mismo
    if (user.isUser && userId) {
      const paramIdOrError = UniqueID.create(userId);
      if (paramIdOrError.isSuccess && user.id.equals(paramIdOrError.data)) {
        return next();
      }
    }

    return ExpressController.errorResponse(
      new ApiError({
        status: 401,
        title: "Unauthorized",
        detail: "You are not authorized to access this resource.",
      }),
      req,
      res
    );
  },
];
