import type { Types } from 'mongoose';

import { ApiError } from '@/shared/utils/errors';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import { UserType } from '@/shared/constants/enum.constant';
import type { IUserDoc } from '@/modules/user/user.interfaces';
import { Team } from '@/modules/teams/teams.model';
import { getObjectId } from '@/shared/utils/commonHelper';
import responseCodes from '@/shared/utils/responseCode/responseCode';

const { TeamResponseCodes } = responseCodes;

export function isAdminOrSuperAdminUser(user: IUserDoc): boolean {
  return (
    user.userType === UserType.ADMIN ||
    user.userType === UserType.SUPERADMIN
  );
}

type TeamAccessFields = {
  _id: Types.ObjectId;
  companyId: Types.ObjectId;
};

export function assertUserCanAccessTeam(
  user: IUserDoc,
  team: TeamAccessFields,
): void {
  const userCompanyId = user.company?.id?.toString();
  if (!userCompanyId || team.companyId.toString() !== userCompanyId) {
    throw new ApiError(
      defaultStatus.FORBIDDEN,
      'You do not have access to this team',
      true,
      '',
      TeamResponseCodes.ROLE_ERROR,
    );
  }

  if (isAdminOrSuperAdminUser(user)) return;

  const tid = team._id.toString();
  const allowed =
    user.team?.some((id) => id.toString() === tid) ?? false;

  if (!allowed) {
    throw new ApiError(
      defaultStatus.FORBIDDEN,
      'You do not have access to this team',
      true,
      '',
      TeamResponseCodes.ROLE_ERROR,
    );
  }
}

export async function assertUserCanAccessTeamById(
  user: IUserDoc,
  teamId: string,
): Promise<void> {
  const team = await Team.findById(getObjectId(teamId))
    .select('_id companyId')
    .lean<TeamAccessFields | null>();

  if (!team) {
    throw new ApiError(
      defaultStatus.NOT_FOUND,
      'Team not found',
      true,
      '',
      TeamResponseCodes.TEAM_NOT_FOUND,
    );
  }

  assertUserCanAccessTeam(user, team);
}
