import mongoose, { Document, Types } from 'mongoose';

import { AccessAndRefreshTokens } from '@/modules/token/token.interfaces';
import { IPaginateModel, IPaginateResult } from '@/shared/interfaces/model.interface';
import { MemberType, Status, UserType } from '@/shared/constants/enum.constant';

export interface IUser {
  firstName: string;
  lastName: string;
  email: string;
  password: string;
  isEmailVerified: boolean;
  phone: {
    dialCode: number;
    number: number;
  };
  team: Types.ObjectId[];
  company: {
    id: Types.ObjectId;
    role: Types.ObjectId[];
  };
  subCompany: {
    id: Types.ObjectId;
    role: Types.ObjectId[];
  };
  reportingTo: Types.ObjectId;
  joiningDate: Date;
  status: Status;
  isDeleted: boolean;
  memberType: MemberType;
  userType: UserType;
  deviceToken: [string];
  deviceType: string;
  createdBy: Types.ObjectId;
  updatedBy: Types.ObjectId;
  subCompanyName?: string;
  lastPermissionUpdate?: Date;
  companyType?: string;
  resetTokenVersion?: number;
  updatedAt?: Date;
  myoperator?: {
    uuid?: string;
    extension?: number;
    syncedAt?: Date;
    syncStatus?: 'synced' | 'failed' | 'pending' | 'not_synced';
  };
}

export interface IUserDoc extends IUser, Document {
  isPasswordMatch(password: string): Promise<boolean>;
  name: string;
}

export interface IUserModel extends IPaginateModel<IUserDoc> {
  isEmailTaken(
    email: string,
    excludeUserId?: mongoose.Types.ObjectId,
  ): Promise<boolean>;
}

export interface IUserPaginateResult extends IPaginateResult<IUserDoc> {
  totalActiveUsers: number;
}
export type UpdateUserBody = Partial<IUser>;

export type NewCreatedUser = Partial<IUser> & { isEmailVerified?: never };

export interface IUserWithTokens {
  user: IUserDoc;
  tokens: AccessAndRefreshTokens;
}

export interface UserQuery {
  'phone.dialCode': number;
  'phone.number': number;
  status: string;
  _id?: { $ne: Types.ObjectId } | string | Types.ObjectId;
}


export interface CheckActivationUniquenessParams {
  userId: Types.ObjectId;
  email?: string;
  phone?: {
    number?: number;
    dialCode?: number;
  };
}