import passport from 'passport';
import { Request, Response, NextFunction } from 'express';

import { ApiError } from '@/shared/utils/errors';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { hasModuleAccess } from '@/shared/utils/checkModuleAccess';
import { IUserDoc } from '@/modules/user/user.interfaces';
import { pick } from '@/shared/utils';
import { Team } from '@/modules/teams/teams.model';
import { getObjectId } from '@/shared/utils/commonHelper';

const { UserResponseCodes } = responseCodes;

const userAuthAndCheckPermissions =
  (moduleName?: string, requiredActions?: string) =>
  async (req: Request, res: Response, next: NextFunction) => {
    const { isViewOnly } = pick(req.query, ['isViewOnly']);
    passport.authenticate(
      'jwt',
      { session: false },
      async (err: Error, user: IUserDoc) => {
        if (err || !user)
          return next(
            new ApiError(
              defaultStatus.UNAUTHORIZED,
              `Please authenticate ${err} ${user}`,
              true,
              '',
              UserResponseCodes.PLEASE_AUTHENTICATE,
            ),
          );

        const teamsWhereLead = await Team.find(
          { lead: user._id },
          '_id',
        ).lean();

        const teamIds = teamsWhereLead.map((t) => t._id.toString());

        const existingTeamIds = user.team.map((id) => id.toString());

        const combined = [...new Set([...existingTeamIds, ...teamIds])];

        user.team = combined.map((id) => getObjectId(id));

        req.user = user;

        // For dropdown get request
        if (isViewOnly) return next();

        if (!moduleName || !requiredActions) return next();

        const companyRoles = user?.company?.role || [];

        const allowed = await hasModuleAccess(
          companyRoles,
          moduleName,
          requiredActions,
        );

        if (!allowed)
          return next(
            new ApiError(
              defaultStatus.FORBIDDEN,
              `You do not have permission to perform this action on module: ${moduleName}`,
            ),
          );

        next();
      },
    )(req, res, next);
  };

export default userAuthAndCheckPermissions;
