import { PipelineStage } from 'mongoose';
import httpStatus from 'http-status';

import User from './user.model';
import { ApiError } from '@/shared/utils/errors';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { Status } from '@/shared/constants/enum.constant';
import { CheckActivationUniquenessParams } from './user.interfaces';
import { getObjectId } from '@/shared/utils/commonHelper';

const { UserResponseCodes } = responseCodes;

export const createUserLookupStages = (): PipelineStage[] => [
  {
    $lookup: {
      from: 'roles',
      let: { roleIds: '$company.role' },
      pipeline: [
        { $match: { $expr: { $in: ['$_id', '$$roleIds'] } } },
        { $addFields: { id: '$_id' } },
        { $project: { _id: 0, id: 1, name: 1 } },
      ],
      as: 'companyRoles',
    },
  },
  { $set: { 'company.role': { $ifNull: ['$companyRoles', []] } } },
  { $unset: 'companyRoles' },

  {
    $lookup: {
      from: 'users',
      let: { rtId: '$reportingTo' },
      pipeline: [
        { $match: { $expr: { $eq: ['$_id', '$$rtId'] } } },
        { $addFields: { id: '$_id' } },
        { $project: { _id: 0, id: 1, firstName: 1, lastName: 1, email: 1 } },
      ],
      as: 'reportingTo',
    },
  },
  { $unwind: { path: '$reportingTo', preserveNullAndEmptyArrays: true } },

  {
    $lookup: {
      from: 'teams',
      let: { teamIds: '$team', userId: '$_id' },
      pipeline: [
        { $match: { $expr: { $in: ['$_id', '$$teamIds'] } } },
        { $addFields: { id: '$_id' } },
        { $project: { _id: 0, id: 1, name: 1, lead: 1, members: 1 } },
      ],
      as: 'team',
    },
  },
  {
    $lookup: {
      from: 'companies',
      let: { companyId: '$company.id' },
      pipeline: [
        { $match: { $expr: { $eq: ['$_id', '$$companyId'] } } },
        { $addFields: { id: '$_id' } },
        { $project: { _id: 0, id: 1, name: 1, companyType: 1 } },
      ],
      as: 'companyDetails',
    },
  },
  { $unwind: { path: '$companyDetails', preserveNullAndEmptyArrays: true } },
];

export const checkUserActivationUniqueness = async ({
  userId,
  email,
  phone,
}: CheckActivationUniquenessParams): Promise<void> => {
  const orConditions: any[] = [];

  if (email) orConditions.push({ email });

  if (phone?.number && phone?.dialCode)
    orConditions.push({
      'phone.number': phone.number,
      'phone.dialCode': phone.dialCode,
    });

  // Nothing to validate
  if (!orConditions.length) return;

  const conflictUser = await User.findOne({
    _id: { $ne: getObjectId(userId) },
    status: Status.ACTIVE,
    $or: orConditions,
  }).lean();

  if (conflictUser)
    throw new ApiError(
      httpStatus.BAD_REQUEST,
      'An active user already exists with the same email or phone number',
      true,
      '',
      UserResponseCodes.USER_ALREADY_ACTIVE_WITH_EMAIL_OR_PHONE,
    );
};
