import { BadRequestException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Admin, AdminDocument } from '../schema/admin.schema';
import mongoose, { Model, Types } from 'mongoose';
import { CustomException } from 'src/exception/custom.exception';
import { Request, Response } from 'express';
import { generateBarcode } from 'src/utils/barcode.util';
import { AdminLoginDto } from './dto/login.dto';
import * as bcrypt from 'bcrypt';
import { ErrorMsg, SuccessMsg } from 'src/utils/response-message.helper';
import { JwtService } from '@nestjs/jwt';
import { User, UserDocument } from 'src/schema/user.schema';
import { Shipment, ShipmentDocument } from 'src/schema/shipment.schema';
import { CreateShipmentDto } from './dto/create-shipment.dto';
import { UserRegisterDto } from './dto/user.register.dto';
import {
  Shipment_Mode,
  Shipment_Mode_Document,
} from 'src/schema/map-shipment-mode.schema';
import { Map_Shipment_Attachment } from 'src/schema/map-shipment-attachment';
import {
  Map_Shipment_Status,
  MapShipmentStatusDocument,
} from 'src/schema/map_shipment_status.schema';
import { AddStatusDto } from './dto/add-status.dto';
import * as fs from 'fs';
import { Inquiry, InquiryDocument } from 'src/schema/inquiry.schema';
import { UpdateShipmentDto } from './dto/update-shipment.dto';
import {
  Map_Company_Employee,
  Map_Company_Employee_Document,
} from 'src/schema/map-company-employees.schema';
import { Otp, OtpDocument } from 'src/schema/otp.schema';
import { VerifyAdminOtpDto } from './dto/verify-otp.dto';
import { ChangePasswordDto } from 'src/users/dto/change-password.dto';
import {
  Notification,
  NotificationDocument,
} from 'src/schema/notifications.schema';
import { notificationHelper } from 'src/utils/notification.helper';
import {
  Map_Inquiry_Reply,
  Map_Inquiry_Reply_Document,
} from 'src/schema/map-inquiry-reply.schema';
import { ReplyInquiryDto } from 'src/users/dto/reply-inquiry.dto';
import {
  Map_Inquiry_Attachment,
  Map_Inquiry_Attachment_Document,
} from 'src/schema/map-inquiry-attachments';
import { CreateShipmentModeDto } from './dto/create-shipment-mode.dto';
import { generateSerialNumber } from 'src/utils/generate-serial-number.helper';
import { NotificationMessages } from 'src/utils/notification-message.helper';
import { getDaysHelper } from 'src/utils/day-helpers';
import { SendFirebaseNotifications } from 'src/utils/send-notification.helper';
import {
  Map_User_Device,
  Map_User_Device_Document,
} from 'src/schema/map-user-device.schema';
import {
  ACTIVE,
  ADMIN,
  BASE_SHIPMENT_SERIAL_NO,
  CHANGE_PASSWORD,
  COMPANY,
  COMPLETED,
  CURRENT_STATE,
  CURRENT_STATUS_ID,
  DELETED_AT,
  DOCUMENT,
  EMPLOYEE,
  EN,
  FIRST_NAME,
  ID,
  IS_COMPANY,
  LANG,
  LAST_LOGIN,
  MONTHLY,
  NEW_SHIPMENT,
  PASSWORD,
  PHONE_NUMBER_VERIFIED_AT,
  QUOTATION,
  REPLY,
  SHIPEMENT_INVOICE,
  SHIPEMENT_STATUS,
  SHIPMENT_DOCUMENT,
  STATUS,
  VERIFY_PHONE_NUMBER,
  YEARLY,
  SHIPMENT_TYPE,
} from 'src/utils/constants';
import {
  Map_Shipment_Commodity,
  Map_Shipment_Commodity_Document,
} from 'src/schema/map-shipment-commodity.schema';
import { DeleteUserDto } from './dto/delete-user.dto';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateSingleUserDto } from './dto/update-single-user.dto';
import { capitalizeFull } from 'src/utils/capitalize.helper';
import { translateData } from 'src/utils/translate';
import { AssignRoleDto } from './dto/assign-role.dto';
import { AddMultiStatusDto } from './dto/add-multi-status.dto';
import { SendMsg91PasswordService } from 'src/utils/send-msg91-password.helper';
import { modifyOtpNumber } from 'src/utils/modifyOtpNumber.helper';
import { Quotation, QuotationDocument } from 'src/schema/quotation.schema';
import { CreateEstimateDto, CreateQuotationDto } from './dto/quotation.dto';
import { Estimate, EstimateDocument } from 'src/schema/estimate.schema';

@Injectable()
export class AdminService {
  constructor(
    @InjectModel(Admin.name) private readonly adminModel: Model<AdminDocument>,
    @InjectModel(User.name) private readonly userModel: Model<UserDocument>,
    @InjectModel(Shipment.name)
    private readonly shipmentModel: Model<ShipmentDocument>,
    @InjectModel(Shipment_Mode.name)
    private readonly shipmentModeModel: Model<Shipment_Mode_Document>,
    private readonly jwtService: JwtService,
    @InjectModel(Map_Shipment_Attachment.name)
    private readonly mapShipmentAttachmentModel: Model<Map_Shipment_Attachment>,
    @InjectModel(Map_Shipment_Status.name)
    private readonly mapShipmentStatusModel: Model<MapShipmentStatusDocument>,
    @InjectModel(Inquiry.name)
    private readonly inquiryModel: Model<InquiryDocument>,
    @InjectModel(Map_Company_Employee.name)
    private readonly mapCompanyEmployeeModel: Model<Map_Company_Employee_Document>,
    @InjectModel(Otp.name) private readonly otpModel: Model<OtpDocument>,
    @InjectModel(Notification.name)
    private readonly notificationModel: Model<NotificationDocument>,
    @InjectModel(Map_Inquiry_Reply.name)
    private readonly mapInquiryReplyModel: Model<Map_Inquiry_Reply_Document>,
    @InjectModel(Map_Inquiry_Attachment.name)
    private readonly mapInquiryAttachmentModel: Model<Map_Inquiry_Attachment_Document>,
    private readonly sendFirbaseNotificationService: SendFirebaseNotifications,
    @InjectModel(Map_User_Device.name)
    private readonly mapUserDeviceModal: Model<Map_User_Device_Document>,
    @InjectModel(Quotation.name)
    private readonly quotationModal: Model<QuotationDocument>,
    @InjectModel(Estimate.name)
    private readonly estimateModal: Model<EstimateDocument>,
    @InjectModel(Map_Shipment_Commodity.name)
    private readonly mapShipmentCommodityModal: Model<Map_Shipment_Commodity_Document>,
    private readonly sendMsg91PasswordService: SendMsg91PasswordService,
  ) {}

  /*************************************ADMIN LOGIN**************************************/
  async adminLogin(lang: string, body: AdminLoginDto, res: Response) {
    try {
      const admin = await this.adminModel.findOne({ email: body.email });
      if (!admin) {
        throw new BadRequestException(
          ErrorMsg?.INVALID_CREDENTIALS[lang || EN],
        );
      }

      //////////Matching Password///////////
      const isMatch = await bcrypt.compare(body?.password, admin?.password);

      if (!isMatch) {
        throw new BadRequestException(
          ErrorMsg?.INVALID_CREDENTIALS[lang || EN],
        );
      }
      const payload = {
        id: admin?._id,
        role: ADMIN,
      };
      const token = await this.jwtService.sign(payload, {
        secret: process.env.JWT_SECRET_KEY,
        expiresIn: '24h',
      });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg.LOGIN_SUCCESSFULL[lang || EN],
        role: ADMIN,
        token,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************************DASHBOARD****************************************/
  async dashboard(report = MONTHLY, res: Response) {
    try {
      let starting; ///////starting date for finding data
      let ending; ///////ending date for finding data
      if (report === YEARLY) {
        starting = new Date(`${new Date().getFullYear()}-01-01T00:00:00.000Z`);
        ending = new Date(`${new Date().getFullYear()}-12-31T23:59:59.999Z`);
      } else if (report === MONTHLY) {
        starting = new Date(
          `${new Date().getFullYear()}-${new Date().getUTCMonth()}-01T00:00:00.000Z`,
        );
        ending = new Date(
          `${new Date().getFullYear()}-${new Date().getUTCMonth()}-${getDaysHelper()}T23:59:59.000Z`,
        );
      } else {
        const today = new Date().getUTCDate();
        const startDate = new Date(
          new Date().setUTCDate(today - 7),
        ).getUTCDate();
        const startMonth = new Date(
          new Date().setUTCDate(today - 7),
        ).getUTCMonth();
        const startYear = new Date(
          new Date().setUTCDate(today - 7),
        ).getUTCFullYear();
        starting = new Date(
          `${startYear}-${startMonth + 1}-${startDate}T00:00:00.000Z`,
        );
        ending = new Date();
      }
      //////////completed shipments data////////
      const completed = await this.getStatistics(
        COMPLETED,
        report,
        starting,
        ending,
      );
      //////////active shipments data///////////
      const active = await this.getStatistics(ACTIVE, report, starting, ending);
      /////////total shipments data///////////
      const total = await this.getStatistics(null, report, starting, ending);
      const label = total?.label;
      const series = [active?.series, completed?.series, total?.series];
      const totalUsers = await this.userModel.countDocuments({
        last_login: { $ne: null },
      });
      const recentUsers = await this.userModel
        .find({ last_login: { $ne: null }, is_blocked: false })
        .select({ password: 0 })
        .sort({ createdAt: -1 })
        .limit(5);
      const shipments = await this.shipmentModel.aggregate([
        {
          $lookup: {
            from: 'users',
            as: 'user',
            localField: 'company_id',
            foreignField: '_id',
          },
        },
        {
          $unwind: { path: '$user' },
        },
        {
          $group: {
            _id: '$current_state',
            count: { $sum: 1 },
          },
        },
      ]);
      const completedShipments = shipments.find(
        (item) => item?._id === COMPLETED,
      );
      const activeShipments = shipments.find((item) => item?._id === ACTIVE);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        totalUsers,
        recentUsers,
        completedShipments: completedShipments?.count || 0,
        activeShipments: activeShipments?.count || 0,
        totalShipments:
          (completedShipments?.count || 0) + (activeShipments?.count || 0),
        label,
        series,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************************FORGOT PASSWORD**********************************/
  async forgotPassword(lang: string, res: Response) {
    try {
      const findOtp = await this.otpModel.findOne({
        phone_number: '9898989898',
        expired_at: { $gte: new Date() },
      });
      if (findOtp) {
        throw new BadRequestException(ErrorMsg?.OTP_NOT_FOUND[lang || EN]);
      }
      await new this.otpModel({
        phone_number: '9898989898',
        action: VERIFY_PHONE_NUMBER,
        otp: 123456,
        expired_at: new Date(new Date().getTime() + 2 * 60 * 1000),
      }).save();
      return res.status(HttpStatus.CREATED).json({
        success: true,
        message: SuccessMsg?.OTP_SENT[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************************VERIFY OTP***************************************/
  async verifyOtp(lang: string, body: VerifyAdminOtpDto, res: Response) {
    try {
      const findOtp = await this.otpModel.findOne({
        phone_number: '9898989898',
        action: body?.action,
      });
      if (!findOtp) {
        throw new BadRequestException(ErrorMsg?.OTP_NOT_FOUND[lang ?? EN]);
      }
      if (findOtp?.otp !== body?.otp) {
        throw new BadRequestException(ErrorMsg?.WRONG_OTP_ENTERED[lang || EN]);
      }
      const admin = await this.adminModel.findOne();
      const payload = {
        id: admin?._id,
        role: ADMIN,
      };
      const token = await this.jwtService.sign(payload, {
        secret: process.env.JWT_SECRET_KEY,
        expiresIn: '24h',
      });
      await this.otpModel.findByIdAndDelete(findOtp?._id);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        message: SuccessMsg?.OTP_VERIFIED[lang || EN],
        token,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************CHANGE PASSWORD***************************************/
  async changePassword(
    req: Request,
    lang: string,
    body: ChangePasswordDto,
    res: Response,
  ) {
    try {
      if (req[ADMIN][FIRST_NAME]) {
        throw new BadRequestException(
          ErrorMsg?.AUTHENTICATION_FAILED[lang || EN],
        );
      }
      if (body?.new_password !== body?.confirm_password) {
        throw new BadRequestException(
          ErrorMsg?.BOTH_PASSWORD_MATCH[lang || EN],
        );
      }
      if (body?.type === CHANGE_PASSWORD) {
        const matchPassword = await bcrypt.compare(
          body?.old_password,
          req[ADMIN][PASSWORD],
        );
        if (!matchPassword) {
          throw new BadRequestException(
            ErrorMsg?.WRONG_PASSWORD_ENTERED[lang ?? EN],
          );
        }
      }
      const hashedPassword = await bcrypt.hash(body?.new_password, 10);
      await this.adminModel.findByIdAndUpdate(req[ADMIN][ID], {
        password: hashedPassword,
      });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.PASSWORD_CHANGED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************GET ALL SHIPMENTS*************************************/
  // async getAllShipments(
  //   res: Response,
  //   lang: string,
  //   page = 1,
  //   limit = 10,
  //   search = '',
  //   status = '',
  //   modeId = '',
  //   shipment_type?: SHIPMENT_TYPE,
  // ) {
  //   try {
  //     ///////////Projection fields for user////////////
  //     const project = {
  //       customer_name: 1,
  //       customer_phone_number: 1,
  //       user_id: 1,
  //       job_id: 1,
  //       name_en: 1,
  //       name_ar: 1,
  //       pickup_from_en: 1,
  //       pickup_from_ar: 1,
  //       delivered_to_en: 1,
  //       delivered_to_ar: 1,
  //       container_number: 1,
  //       current_state: 1,
  //       serial_number: 1,
  //       eta: 1,
  //       current_status: 1,
  //       commodity: 1,
  //       person_name_agent: 1,
  //       shipment_type: 1,
  //     };
  //     //////////Creating query if status sent////////
  //     const query = {};
  //     if (status === COMPLETED) {
  //       query[CURRENT_STATE] = COMPLETED;
  //     } else if (status === ACTIVE) {
  //       query[CURRENT_STATE] = ACTIVE;
  //     }
  //     if (modeId) {
  //       console.log(modeId ,"modeId")
  //       query['shipment_mode'] = new Types.ObjectId(modeId);
  //     }
  //     if (shipment_type) {
  //       query['shipment_type'] = shipment_type;
  //     }

  //     const data = await this.shipmentModel.aggregate([
  //       {
  //         $lookup: {
  //           from: 'users',
  //           as: 'user',
  //           let: { user_id: '$company_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: {
  //                   $eq: ['$_id', '$$user_id'],
  //                 },
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       {
  //         $unwind: {
  //           path: '$user',
  //         },
  //       },
  //       {
  //         $lookup: {
  //           from: 'map_shipment_statuses',
  //           as: 'map_shipment_statuses',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: {
  //                   $eq: ['$shipment_id', '$$shipment_id'],
  //                 },
  //               },
  //             },
  //             { $sort: { createdAt: -1 } },
  //           ],
  //         },
  //       },
  //       {
  //         $lookup: {
  //           from: 'shipment_modes',
  //           as: 'shipment_mode',
  //           let: { mode_id: '$shipment_mode' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: {
  //                   $eq: ['$_id', '$$mode_id'],
  //                 },
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       {
  //         $unwind: { path: '$shipment_mode', preserveNullAndEmptyArrays: true },
  //       },
  //       {
  //         $lookup: {
  //           from: 'map_shipment_commodities',
  //           as: 'commodity',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: {
  //                   $eq: ['$shipment_id', '$$shipment_id'],
  //                 },
  //               },
  //             },
  //             {
  //               $project: {
  //                 name_en: 1,
  //                 name_ar: 1,
  //                 volume: 1,
  //                 weight: 1,
  //                 quantity: 1,
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       {
  //         $lookup: {
  //           from: 'map_shipment_attachments',
  //           as: 'barcode',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
  //                 name: 'barcode',
  //               },
  //             },
  //             { $sort: { createdAt: -1 } },
  //             {
  //               $project: {
  //                 image: { $concat: [process.env.BASE_URL, '$path'] },
  //                 uploaded_by: 1,
  //                 createdAt: 1,
  //                 original_name: 1,
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       { $sort: { createdAt: -1 } },
  //       {
  //         $addFields: {
  //           customer_name: {
  //             $concat: ['$user.first_name', ' ', '$user.last_name'],
  //           },
  //           current_status: { $arrayElemAt: ['$map_shipment_statuses', 0] },
  //           commodity: '$commodity',
  //           barcode: '$barcode',
  //         },
  //       },
  //       {
  //         $match: {
  //           $or: [
  //             { pickup_from_en: { $regex: `.*${search}.*`, $options: 'i' } },
  //             { pickup_from_ar: { $regex: `.*${search}.*`, $options: 'i' } },
  //             { delivered_to_en: { $regex: `.*${search}.*`, $options: 'i' } },
  //             { delivered_to_ar: { $regex: `.*${search}.*`, $options: 'i' } },
  //             { job_id: { $regex: `.*${search}.*`, $options: 'i' } },
  //             { customer_name: { $regex: `.*${search}.*`, $options: 'i' } },
  //             { serial_number: { $regex: `.*${search}.*`, $options: 'i' } },
  //           ],
  //           ...query,
  //         },
  //       },
  //       {
  //         $project: {
  //           ...project,
  //           barcode: 1,
  //           shipment_mode: 1,
  //         },
  //       },
  //       {
  //         $facet: {
  //           paginatedResults: [
  //             { $skip: (Number(page) - 1) * Number(limit) },
  //             { $limit: Number(limit) },
  //           ],
  //           totalCount: [{ $count: 'count' }],
  //         },
  //       },
  //       {
  //         $addFields: {
  //           total: {
  //             $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
  //           },
  //         },
  //       },
  //       {
  //         $project: {
  //           paginatedResults: 1,
  //           total: 1,
  //         },
  //       },
  //     ]);
  //     return res.status(HttpStatus.OK).json({
  //       success: true,
  //       statusCode: 200,
  //       current_page: Number(page),
  //       total_pages: Math.ceil(Number(data[0].total) / Number(limit)) || 0,
  //       limit: Number(limit),
  //       total: Number(data[0].total),
  //       data: data[0].paginatedResults,
  //     });
  //   } catch (error) {
  //     throw new CustomException(error, error.status);
  //   }
  // }

  // async getAllShipments(
  //   res: Response,
  //   lang: string,
  //   page = 1,
  //   limit = 10,
  //   search = '',
  //   status = '',
  //   modeId = '',
  //   shipment_type?: SHIPMENT_TYPE,
  // ) {
  //   try {
  //     /////////// Projection fields for user ////////////
  //     const project = {
  //       customer_name: 1,
  //       customer_phone_number: 1,
  //       user_id: 1,
  //       job_id: 1,
  //       name_en: 1,
  //       name_ar: 1,
  //       pickup_from_en: 1,
  //       pickup_from_ar: 1,
  //       delivered_to_en: 1,
  //       delivered_to_ar: 1,
  //       container_number: 1,
  //       current_state: 1,
  //       serial_number: 1,
  //       eta: 1,
  //       current_status: 1,
  //       commodity: 1,
  //       person_name_agent: 1,
  //       shipment_type: 1,
  //     };

  //     /////////// Create query filters ////////////
  //     const query: any = {};
  //     if (status === COMPLETED) {
  //       query[CURRENT_STATE] = COMPLETED;
  //     } else if (status === ACTIVE) {
  //       query[CURRENT_STATE] = ACTIVE;
  //     }

  //     if (modeId) {
  //       query['shipment_mode'] = new Types.ObjectId(modeId);
  //     }

  //     let shipmentModeDoc = null;
  //     if (modeId) {
  //       shipmentModeDoc = await this.shipmentModeModel.findById(modeId);
  //     }

  //     let shipmentSlug = shipmentModeDoc?.slug?.toLowerCase() === 'lcl';
  //     if (shipmentSlug) {
  //       if (shipment_type) {
  //         query['shipment_type'] = shipment_type;
  //       }
  //     }

  //     if (shipmentSlug && shipment_type == "UAE") {

  //       const pipeline: any[] = [];
  //       const matchStage: any = { ...query };
  //       if (search) {
  //         matchStage.$or = [
  //           { pickup_from_en: { $regex: search, $options: 'i' } },
  //           { pickup_from_ar: { $regex: search, $options: 'i' } },
  //           { delivered_to_en: { $regex: search, $options: 'i' } },
  //           { delivered_to_ar: { $regex: search, $options: 'i' } },
  //           { job_id: { $regex: search, $options: 'i' } },
  //           { serial_number: { $regex: search, $options: 'i' } },
  //         ];
  //       }
  //       pipeline.push({ $match: matchStage });
  //       // Lookup user, statuses, commodities, barcode
  //       pipeline.push(
  //         {
  //           $lookup: {
  //             from: 'users',
  //             as: 'user',
  //             let: { user_id: '$company_id' },
  //             pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$user_id'] } } }],
  //           },
  //         },
  //         { $unwind: '$user' },
  //         {
  //           $lookup: {
  //             from: 'map_shipment_statuses',
  //             as: 'map_shipment_statuses',
  //             let: { shipment_id: '$_id' },
  //             pipeline: [
  //               {
  //                 $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } },
  //               },
  //               { $sort: { createdAt: -1 } },
  //             ],
  //           },
  //         },
  //         {
  //           $lookup: {
  //             from: 'map_shipment_commodities',
  //             as: 'commodity',
  //             let: { shipment_id: '$_id' },
  //             pipeline: [
  //               {
  //                 $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } },
  //               },
  //               {
  //                 $project: {
  //                   name_en: 1,
  //                   name_ar: 1,
  //                   volume: 1,
  //                   weight: 1,
  //                   quantity: 1,
  //                 },
  //               },
  //             ],
  //           },
  //         },
  //         {
  //           $lookup: {
  //             from: 'shipment_modes',
  //             as: 'shipment_mode',
  //             let: { mode_id: '$shipment_mode' },
  //             pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$mode_id'] } } }],
  //           },
  //         },
  //         {
  //           $unwind: {
  //             path: '$shipment_mode',
  //             preserveNullAndEmptyArrays: true,
  //           },
  //         },
  //         {
  //           $lookup: {
  //             from: 'map_shipment_attachments',
  //             as: 'barcode',
  //             let: { shipment_id: '$_id' },
  //             pipeline: [
  //               {
  //                 $match: {
  //                   $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
  //                   name: 'barcode',
  //                 },
  //               },
  //               { $sort: { createdAt: -1 } },
  //               {
  //                 $project: {
  //                   image: { $concat: [process.env.BASE_URL, '$path'] },
  //                   uploaded_by: 1,
  //                   createdAt: 1,
  //                   original_name: 1,
  //                 },
  //               },
  //             ],
  //           },
  //         },
  //         {
  //           $lookup: {
  //             from: 'map_shipment_attachments',
  //             as: 'receiving_slip',
  //             let: { shipment_id: '$_id' },
  //             pipeline: [
  //               {
  //                 $match: {
  //                   $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
  //                   name: 'receiving_slip',
  //                 },
  //               },
  //               { $sort: { createdAt: -1 } },
  //               {
  //                 $project: {
  //                   image: { $concat: [process.env.BASE_URL, '$path'] },
  //                   uploaded_by: 1,
  //                   createdAt: 1,
  //                   original_name: 1,
  //                 },
  //               },
  //             ],
  //           },
  //         },
  //         {
  //           $addFields: {
  //             customer_name: {
  //               $concat: ['$user.first_name', ' ', '$user.last_name'],
  //             },
  //             current_status: { $arrayElemAt: ['$map_shipment_statuses', 0] },
  //           },
  //         },
  //       );
  //       pipeline.push({ $unwind: '$container_number' });
  //       pipeline.push({
  //         $group: {
  //           _id: '$container_number',
  //           container_number: { $first: '$container_number' },
  //           shipments: { $push: '$$ROOT' },
  //         },
  //       });
  //       pipeline.push({
  //          $sort: { 'shipments.createdAt': -1, _id: -1 },
  //       });
  //       pipeline.push({
  //         $facet: {
  //           paginatedResults: [
  //             { $skip: (Number(page) - 1) * Number(limit) },
  //             { $limit: Number(limit) },
  //           ],
  //           totalCount: [{ $count: 'count' }],
  //         },
  //       });
  //       pipeline.push({
  //         $addFields: {
  //           total: { $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0] },
  //         },
  //       });
  //       pipeline.push({
  //         $project: {
  //           paginatedResults: 1,
  //           total: 1,
  //           _id: 0, // hide the _id
  //           container_number: 1,
  //           shipments: 1,
  //         },
  //       });

  //       const data = await this.shipmentModel.aggregate(pipeline);

  //       return res.status(HttpStatus.OK).json({
  //         success: true,
  //         statusCode: 200,
  //         current_page: Number(page),
  //         total_pages:
  //           Math.ceil(Number(data[0]?.total || 0) / Number(limit)) || 0,
  //         limit: Number(limit),
  //         total: Number(data[0]?.total || 0),
  //         isLcl: shipmentSlug,
  //         data: data[0]?.paginatedResults || [],
  //       });
  //     }

  //     /////////// Build pipeline ////////////
  //     const pipeline: any[] = [];

  //     // ✅ Apply filters + search before lookups
  //     const matchStage: any = { ...query };

  //     if (search) {
  //       matchStage.$or = [
  //         { pickup_from_en: { $regex: `.*${search}.*`, $options: 'i' } },
  //         { pickup_from_ar: { $regex: `.*${search}.*`, $options: 'i' } },
  //         { delivered_to_en: { $regex: `.*${search}.*`, $options: 'i' } },
  //         { delivered_to_ar: { $regex: `.*${search}.*`, $options: 'i' } },
  //         { job_id: { $regex: `.*${search}.*`, $options: 'i' } },
  //         { customer_name: { $regex: `.*${search}.*`, $options: 'i' } },
  //         { serial_number: { $regex: `.*${search}.*`, $options: 'i' } },
  //       ];
  //     }

  //     pipeline.push({ $match: matchStage });

  //     /////////// Lookups ////////////
  //     pipeline.push(
  //       {
  //         $lookup: {
  //           from: 'users',
  //           as: 'user',
  //           let: { user_id: '$company_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: { $eq: ['$_id', '$$user_id'] },
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       { $unwind: { path: '$user' } },
  //       {
  //         $lookup: {
  //           from: 'map_shipment_statuses',
  //           as: 'map_shipment_statuses',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             { $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } } },
  //             { $sort: { createdAt: -1 } },
  //           ],
  //         },
  //       },
  //       {
  //         $lookup: {
  //           from: 'shipment_modes',
  //           as: 'shipment_mode',
  //           let: { mode_id: '$shipment_mode' },
  //           pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$mode_id'] } } }],
  //         },
  //       },
  //       {
  //         $unwind: {
  //           path: '$shipment_mode',
  //           preserveNullAndEmptyArrays: true,
  //         },
  //       },
  //       {
  //         $lookup: {
  //           from: 'map_shipment_commodities',
  //           as: 'commodity',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             {
  //               $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } },
  //             },
  //             {
  //               $project: {
  //                 name_en: 1,
  //                 name_ar: 1,
  //                 volume: 1,
  //                 weight: 1,
  //                 quantity: 1,
  //               },
  //             },
  //           ],
  //         },
  //       },

  //       {
  //         $lookup: {
  //           from: 'map_shipment_attachments',
  //           as: 'barcode',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
  //                 name: 'barcode',
  //               },
  //             },
  //             { $sort: { createdAt: -1 } },
  //             {
  //               $project: {
  //                 image: { $concat: [process.env.BASE_URL, '$path'] },
  //                 uploaded_by: 1,
  //                 createdAt: 1,
  //                 original_name: 1,
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       {
  //         $lookup: {
  //           from: 'map_shipment_attachments',
  //           as: 'receiving_slip',
  //           let: { shipment_id: '$_id' },
  //           pipeline: [
  //             {
  //               $match: {
  //                 $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
  //                 name: 'receiving_slip',
  //               },
  //             },
  //             { $sort: { createdAt: -1 } },
  //             {
  //               $project: {
  //                 image: { $concat: [process.env.BASE_URL, '$path'] },
  //                 uploaded_by: 1,
  //                 createdAt: 1,
  //                 original_name: 1,
  //               },
  //             },
  //           ],
  //         },
  //       },
  //       { $sort: { createdAt: -1 } },
  //       {
  //         $addFields: {
  //           customer_name: {
  //             $concat: ['$user.first_name', ' ', '$user.last_name'],
  //           },
  //           current_status: { $arrayElemAt: ['$map_shipment_statuses', 0] },
  //           commodity: '$commodity',
  //           barcode: '$barcode',
  //         },
  //       },
  //       {
  //         $project: {
  //           ...project,
  //           barcode: 1,
  //           shipment_mode: 1,
  //           receiving_slip: 1
  //         },
  //       },
  //       {
  //         $facet: {
  //           paginatedResults: [
  //             { $skip: (Number(page) - 1) * Number(limit) },
  //             { $limit: Number(limit) },
  //           ],
  //           totalCount: [{ $count: 'count' }],
  //         },
  //       },
  //       {
  //         $addFields: {
  //           total: {
  //             $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
  //           },
  //         },
  //       },
  //       {
  //         $project: {
  //           paginatedResults: 1,
  //           total: 1,
  //         },
  //       },
  //     );

  //     const data = await this.shipmentModel.aggregate(pipeline);

  //     return res.status(HttpStatus.OK).json({
  //       success: true,
  //       statusCode: 200,
  //       current_page: Number(page),
  //       total_pages:
  //         Math.ceil(Number(data[0]?.total || 0) / Number(limit)) || 0,
  //       limit: Number(limit),
  //       total: Number(data[0]?.total || 0),
  //       isLcl: shipmentSlug,
  //       data: data[0]?.paginatedResults || [],
  //     });
  //   } catch (error) {
  //     throw new CustomException(error, error.status);
  //   }
  // }

  async getAllShipments(
    res: Response,
    lang: string,
    page = 1,
    limit = 10,
    search = '',
    status = '',
    modeId = '',
    shipment_type?: SHIPMENT_TYPE,
    userId?: string,
  ) {
    try {
      /////////// Projection fields ////////////
      const project = {
        customer_name: 1,
        customer_phone_number: 1,
        user_id: 1,
        job_id: 1,
        name_en: 1,
        name_ar: 1,
        pickup_from_en: 1,
        pickup_from_ar: 1,
        delivered_to_en: 1,
        delivered_to_ar: 1,
        container_number: 1,
        current_state: 1,
        serial_number: 1,
        agent: 1,
        person_name_agent: 1,
        eta: 1,
        current_status: 1,
        commodity: 1,
        shipment_type: 1,
      };

      /////////// Create query filters ////////////
      const query: any = {};
      if (status === COMPLETED) query[CURRENT_STATE] = COMPLETED;
      else if (status === ACTIVE) query[CURRENT_STATE] = ACTIVE;

      if (modeId) query['shipment_mode'] = new Types.ObjectId(modeId);
      const shipmentModeDoc = modeId
        ? await this.shipmentModeModel.findById(modeId)
        : null;

      if (userId) {
        query['company_id'] = new Types.ObjectId(userId);
      }
      let isLclInfo =
        shipmentModeDoc?.slug == 'LCL' || shipmentModeDoc?.slug == 'lcl';
      if (shipment_type && isLclInfo) {
        // query['shipment_type'] = shipment_type;
        query['$or'] = [
          { shipment_type: shipment_type },
          { shipment_type: null },
          { shipment_type: { $exists: false } },
        ];
      }
      // ==========================================================
      // ===================== LCL CASE ===========================
      // ==========================================================
      if (isLclInfo && shipment_type == 'UAE') {
        const pipeline: any[] = [];
        pipeline.push({ $match: { ...query } });

        //  Lookups
        pipeline.push(
          {
            $lookup: {
              from: 'users',
              as: 'user',
              let: { user_id: '$company_id' },
              pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$user_id'] } } }],
            },
          },
          { $unwind: '$user' },
          {
            $lookup: {
              from: 'map_shipment_statuses',
              as: 'map_shipment_statuses',
              let: { shipment_id: '$_id' },
              pipeline: [
                {
                  $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } },
                },
                { $sort: { createdAt: -1 } },
              ],
            },
          },
          {
            $lookup: {
              from: 'map_shipment_commodities',
              as: 'commodity',
              let: { shipment_id: '$_id' },
              pipeline: [
                {
                  $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } },
                },
                {
                  $project: {
                    name_en: 1,
                    name_ar: 1,
                    volume: 1,
                    weight: 1,
                    quantity: 1,
                    quantity_loaded: 1,
                    commodity_description: 1,
                  },
                },
              ],
            },
          },
          {
            $lookup: {
              from: 'shipment_modes',
              as: 'shipment_mode',
              let: { mode_id: '$shipment_mode' },
              pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$mode_id'] } } }],
            },
          },
          {
            $unwind: {
              path: '$shipment_mode',
              preserveNullAndEmptyArrays: true,
            },
          },
          {
            $lookup: {
              from: 'map_shipment_attachments',
              as: 'barcode',
              let: { shipment_id: '$_id' },
              pipeline: [
                {
                  $match: {
                    $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
                    name: 'barcode',
                  },
                },
                { $sort: { createdAt: -1 } },
                {
                  $project: {
                    image: { $concat: [process.env.BASE_URL, '$path'] },
                    uploaded_by: 1,
                    createdAt: 1,
                    original_name: 1,
                  },
                },
              ],
            },
          },
          {
            $lookup: {
              from: 'map_shipment_attachments',
              as: 'receiving_slip',
              let: { shipment_id: '$_id' },
              pipeline: [
                {
                  $match: {
                    $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
                    name: 'receiving_slip',
                  },
                },
                { $sort: { createdAt: -1 } },
                {
                  $project: {
                    image: { $concat: [process.env.BASE_URL, '$path'] },
                    uploaded_by: 1,
                    createdAt: 1,
                    original_name: 1,
                  },
                },
              ],
            },
          },
          {
            $addFields: {
              customer_name: {
                $concat: ['$user.first_name', ' ', '$user.last_name'],
              },
              current_status: { $arrayElemAt: ['$map_shipment_statuses', 0] },
            },
          },
        );

        //  Apply search AFTER lookups & addFields
        if (search) {
          const regex = new RegExp(search, 'i');
          pipeline.push({
            $match: {
              $or: [
                { pickup_from_en: regex },
                { pickup_from_ar: regex },
                { delivered_to_en: regex },
                { delivered_to_ar: regex },
                { 'commodity.name_en': regex },
                { 'commodity.name_ar': regex },
                { customer_name: regex },
                { job_id: regex },
                { 'user.phone_number': regex },
                { serial_number: regex },
                { agent: regex },
                { person_name_agent: regex },
              ],
            },
          });
        }

        // Group, sort, and paginate
        pipeline.push(
          { $unwind: '$container_number' },
          {
            $group: {
              _id: '$container_number',
              container_number: { $first: '$container_number' },
              shipments: { $push: '$$ROOT' },
            },
          },
          { $sort: { 'shipments.createdAt': -1, _id: -1 } },
          {
            $facet: {
              paginatedResults: [
                { $skip: (Number(page) - 1) * Number(limit) },
                { $limit: Number(limit) },
              ],
              totalCount: [{ $count: 'count' }],
            },
          },
          {
            $addFields: {
              total: {
                $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
              },
            },
          },
          {
            $project: {
              paginatedResults: 1,
              total: 1,
              _id: 0,
            },
          },
        );

        const data = await this.shipmentModel.aggregate(pipeline);
        return res.status(HttpStatus.OK).json({
          success: true,
          statusCode: 200,
          current_page: Number(page),
          total_pages:
            Math.ceil(Number(data[0]?.total || 0) / Number(limit)) || 0,
          limit: Number(limit),
          total: Number(data[0]?.total || 0),
          isLcl: true,
          data: data[0]?.paginatedResults || [],
        });
      }

      // ==========================================================
      // ===================== NON-LCL CASE =======================
      // ==========================================================
      const pipeline: any[] = [];
      pipeline.push({ $match: { ...query } });

      // Lookups
      pipeline.push(
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$company_id' },
            pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$user_id'] } } }],
          },
        },
        { $unwind: '$user' },
        {
          $lookup: {
            from: 'map_shipment_statuses',
            as: 'map_shipment_statuses',
            let: { shipment_id: '$_id' },
            pipeline: [
              { $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } } },
              { $sort: { createdAt: -1 } },
              { $limit: 1 },  // this is add after api optimize for performance
            ],
          },
        },
        {
          $lookup: {
            from: 'shipment_modes',
            as: 'shipment_mode',
            let: { mode_id: '$shipment_mode' },
            pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$mode_id'] } } }],
          },
        },
        {
          $unwind: { path: '$shipment_mode', preserveNullAndEmptyArrays: true },
        },
        {
          $lookup: {
            from: 'map_shipment_commodities',
            as: 'commodity',
            let: { shipment_id: '$_id' },
            pipeline: [
              { $match: { $expr: { $eq: ['$shipment_id', '$$shipment_id'] } } },
              {
                $project: {
                  name_en: 1,
                  name_ar: 1,
                  volume: 1,
                  weight: 1,
                  quantity: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'barcode',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
                  name: 'barcode',
                },
              },
              { $sort: { createdAt: -1 } },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'receiving_slip',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
                  name: 'receiving_slip',
                },
              },
              { $sort: { createdAt: -1 } },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $addFields: {
            customer_name: {
              $concat: ['$user.first_name', ' ', '$user.last_name'],
            },
            current_status: { $arrayElemAt: ['$map_shipment_statuses', 0] },
          },
        },
      );

      //  Apply search AFTER lookups
      if (search) {
        const regex = new RegExp(search, 'i');
        pipeline.push({
          $match: {
            $or: [
              { pickup_from_en: regex },
              { pickup_from_ar: regex },
              { delivered_to_en: regex },
              { delivered_to_ar: regex },
              { 'commodity.name_en': regex },
              { 'commodity.name_ar': regex },
              { customer_name: regex },
              { 'user.phone_number': regex },
              { job_id: regex },
              { serial_number: regex },
              { agent: regex },
              { person_name_agent: regex },
            ],
          },
        });
      }
      // Sorting, pagination, projection
      pipeline.push(
        { $sort: { createdAt: -1 } },
        {
          $project: {
            ...project,
            barcode: 1,
            shipment_mode: 1,
            receiving_slip: 1,
          },
        },
        {
          $facet: {
            paginatedResults: [
              { $skip: (Number(page) - 1) * Number(limit) },
              { $limit: Number(limit) },
            ],
            totalCount: [{ $count: 'count' }],
          },
        },
        {
          $addFields: {
            total: { $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0] },
          },
        },
        { $project: { paginatedResults: 1, total: 1 } },
      );

      const data = await this.shipmentModel.aggregate(pipeline);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        current_page: Number(page),
        total_pages:
          Math.ceil(Number(data[0]?.total || 0) / Number(limit)) || 0,
        limit: Number(limit),
        total: Number(data[0]?.total || 0),
        isLcl: isLclInfo,
        data: data[0]?.paginatedResults || [],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  // @@ total active /complete shipment count
  async getTotalCount() {
    try {
      // ---------- 1. Fetch all shipment modes ----------
      const allModes = await this.shipmentModeModel.find(
        {},
        { _id: 1, name: 1, slug: 1 },
      );

      // ---------- 2. Prepare base response ----------
      const response: any = {
        totalActive: 0,
        totalComplete: 0,
        totalShipment: 0,
        modes: {},
      };

      // ---------- 3. Global totals ----------
      const [totalActive, totalComplete, totalShipment] = await Promise.all([
        this.shipmentModel.countDocuments({ current_state: ACTIVE }),
        this.shipmentModel.countDocuments({ current_state: COMPLETED }),
        this.shipmentModel.countDocuments({}),
      ]);

      response.totalActive = totalActive;
      response.totalComplete = totalComplete;
      response.totalShipment = totalShipment;

      // ---------- 4. Per–mode totals ----------
      await Promise.all(
        allModes.map(async (mode) => {
          const modeId = mode._id.toString();

          const [modeActive, modeComplete, modeTotal] = await Promise.all([
            this.shipmentModel.countDocuments({
              current_state: ACTIVE,
              shipment_mode: mode._id,
            }),
            this.shipmentModel.countDocuments({
              current_state: COMPLETED,
              shipment_mode: mode._id,
            }),
            this.shipmentModel.countDocuments({
              shipment_mode: mode._id,
            }),
          ]);

          response.modes[modeId] = {
            mode_name: mode.slug,
            totalActive: modeActive,
            totalComplete: modeComplete,
            totalShipment: modeTotal,
          };
        }),
      );

      // ---------- 5. Return clean result ----------
      return {
        success: true,
        statusCode: 200,
        ...response,
      };
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  /*------------------------------------------------------------------------------------*/

  /********************************CREATE SHIPMENT***************************************/
  async createShipment(
    req: Request,
    lang: string,
    notify: boolean,
    body: CreateShipmentDto,
    files: {
      shipment_document?: Express.Multer.File[];
      shipment_invoice?: Express.Multer.File[];
      receiving_slip?: Express.Multer.File[];
    },
    res: Response,
  ) {
    try {
      let allFiles = [];
      if (files?.shipment_document?.length) {
        allFiles = [...files?.shipment_document];
      }
      if (files?.shipment_invoice?.length) {
        allFiles = [...allFiles, ...files?.shipment_invoice];
      }
      if (files?.receiving_slip?.length) {
        allFiles = [...allFiles, ...files?.receiving_slip];
      }
      if (allFiles?.length && req['fileValidationError']) {
        throw new BadRequestException(req['fileValidationError']);
      }
      let findCustomer = {};
      if (body?.company_name) {
        findCustomer = {
          $or: [
            {
              company_name: body?.company_name,
            },
            {
              phone_number: body?.phone_number,
              country_phone_code: body?.country_phone_code,
            },
          ],
        };
      } else {
        findCustomer = {
          phone_number: body?.phone_number,
          country_phone_code: body?.country_phone_code,
        };
      }
      const companyData = await this.userModel?.aggregate([
        {
          $match: {
            ...findCustomer,
            deleted_at: null,
          },
        },
        {
          $lookup: {
            from: 'map_user_devices',
            as: 'devices',
            localField: '_id',
            foreignField: 'user_id',
          },
        },
      ]);
      let company = companyData[0];
      /////////if company is already registered and data says company is new////////
      if (body?.is_new_company === 'true' && company?.is_company === true) {
        throw new BadRequestException(ErrorMsg?.COMPANY_EXIST[lang || EN]);
      } else if (body?.is_new_company === 'true' && !company) {
        company = await new this.userModel({
          first_name: body?.first_name,
          last_name: body?.last_name,
          email: body?.email,
          phone_number: body?.phone_number,
          country_phone_code: body?.country_phone_code,
          company_name: body?.company_name,
          is_company: true,
        }).save();
      } else if (
        body?.is_new_company === 'true' &&
        company?.is_company === false
      ) {
        /////////creating new company from existing user////////
        await this.userModel.findByIdAndUpdate(company?._id, {
          company_name: body?.company_name,
          is_company: true,
        });
      }
      let notificationUsers = [companyData[0]];

      if (body?.employees?.length > 0) {
        for (const employee of body?.employees) {
          const findEmployee = await this.userModel.aggregate([
            {
              $match: {
                phone_number: employee?.phone_number,
                country_phone_code: employee?.country_phone_code,
                deleted_at: null,
              },
            },
            {
              $lookup: {
                from: 'map_user_devices',
                as: 'devices',
                localField: '_id',
                foreignField: 'user_id',
              },
            },
          ]);

          if (findEmployee?.length === 0) {
            ///////adding employees if not exists///////
            const newEmployee = await new this.userModel({
              phone_number: employee?.phone_number,
              first_name: employee?.first_name,
              last_name: employee?.last_name,
              country_phone_code: body?.country_phone_code,
            }).save();
            await new this.mapCompanyEmployeeModel({
              company_id: new mongoose.Types.ObjectId(company?._id),
              employee_id: new mongoose.Types.ObjectId(newEmployee?._id),
              show_invoice: employee?.show_invoice,
            }).save();
            notificationUsers.push(newEmployee);
          } else {
            //////////mapping employees to company//////////
            const employAlreadyExits = await this.mapCompanyEmployeeModel.find({
              company_id: new mongoose.Types.ObjectId(company?._id),
              employee_id: new mongoose.Types.ObjectId(findEmployee[0]?._id),
            });
            if (
              findEmployee[0]?.is_company === false &&
              employAlreadyExits.length == 0
            ) {
              await new this.mapCompanyEmployeeModel({
                company_id: new mongoose.Types.ObjectId(company?._id),
                employee_id: new mongoose.Types.ObjectId(findEmployee[0]?._id),
                show_invoice: employee?.show_invoice,
              }).save();
              notificationUsers.push(findEmployee[0]);
            }
          }
        }
      }

      ///////////////////creating shipment//////////////////
      const shipment = await new this.shipmentModel({
        ...body,
        job_id: `BP#${new Date().getTime()}`,
        shipment_mode: new mongoose.Types.ObjectId(body?.shipment_mode),
        company_id: company?._id,
        serial_number: await this.generateShipmentSerialNumber(),
      }).save();
      // Generate 6-digit verification code
      // const verificationCode = Math.floor(
      //   100000 + Math.random() * 900000,
      // ).toString();
      // const verificationCode = '123456';

      // // Save it in the shipment
      // await this.shipmentModel.findByIdAndUpdate(shipment._id, {
      //   verification_code: verificationCode,
      // });
      //Generate barcode and add it as file
      const barcodeFile = await generateBarcode(
        shipment._id.toString(),
        shipment.serial_number,
      );
      allFiles.push(barcodeFile);
      const allPromise = [];
      ///////////Saving multiple commodities of this shipment/////////////
      for (let i = 0; i < body?.commodity?.length; i++) {
        allPromise.push(() =>
          new this.mapShipmentCommodityModal({
            ...body?.commodity[i],
            shipment_id: new mongoose.Types.ObjectId(shipment?._id),
          }).save(),
        );
      }

      /////////saving file if given////////
      if (allFiles?.length > 0) {
        for (const file of allFiles) {
          allPromise.push(() =>
            new this.mapShipmentAttachmentModel({
              name: file?.fieldname,
              file_name: file?.filename,
              original_name: file?.originalname,
              mime_type: file?.mimetype,
              type: DOCUMENT,
              shipment_id: new mongoose.Types.ObjectId(shipment._id),
              path: file?.path,
              base_url: `${req.protocol}://${req.headers.host}/`,
              uploaded_by: ADMIN,
            }).save(),
          );
        }
      }
      //////////saving status if given///////////
      if (body?.shipment_status) {
        let status_en;
        let status_ar;
        if (lang === EN) {
          status_en = body?.shipment_status;
          status_ar = await translateData(body?.shipment_status, 'ar');
        } else {
          status_en = await translateData(body?.shipment_status, 'en');
          status_ar = body?.shipment_status;
        }
        const newStatus = await new this.mapShipmentStatusModel({
          status_en,
          status_ar,
          shipment_id: new mongoose.Types.ObjectId(shipment?._id),
        }).save();
        await this.shipmentModel.findByIdAndUpdate(shipment?._id, {
          current_status_id: new mongoose.Types.ObjectId(newStatus?._id),
        });
      }

      if (body?.removed_employees) {
        for (let i = 0; i < body?.removed_employees?.length; i++) {
          try {
            allPromise.push(() =>
              this.mapCompanyEmployeeModel.findOneAndDelete({
                company_id: new mongoose.Types.ObjectId(company?._id),
                employee_id: new mongoose.Types.ObjectId(
                  body?.removed_employees[i],
                ),
              }),
            );
          } catch (error) {
            continue;
          }
        }
      }

      if (notify) {
        for (const user of notificationUsers) {
          ///////////////////Device Tokens////////////////
          const deviceTokens = [];
          if (user?.devices?.length > 0) {
            for (const item of user?.devices) {
              deviceTokens.push(item?.device_token);
            }
            allPromise.push(() =>
              this.sendNewShipmentNotification(
                shipment,
                user,
                shipment?._id?.toString(),
                deviceTokens,
              ),
            );
          }
        }
      }
      const resolved = allPromise.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.SHIPMENT_CREATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************UPDATE SHIPMENT***************************************/
  async updateShipment(
    req: Request,
    shipment_id: string,
    notify: boolean,
    lang: string,
    body: UpdateShipmentDto,
    files: {
      shipment_document?: Express.Multer.File[];
      shipment_invoice?: Express.Multer.File[];
      receiving_slip?: Express.Multer.File[];
    },
    res: Response,
  ) {
    try {
      let allFiles = [];
      if (files?.shipment_document?.length) {
        allFiles = [...files?.shipment_document];
      }
      if (files?.shipment_invoice?.length) {
        allFiles = [...allFiles, ...files?.shipment_invoice];
      }
      if (files?.receiving_slip?.length) {
        allFiles = [...allFiles, ...files?.receiving_slip];
      }
      if (allFiles?.length && req['fileValidationError']) {
        throw new BadRequestException(req['fileValidationError']);
      }

      //////////////////////Shipment And Compnay Data/////////////////////
      const shipment = await this.shipmentModel.aggregate([
        { $match: { _id: new mongoose.Types.ObjectId(shipment_id) } },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
      ]);

      ///////////////All Devices////////////////
      const notificationUsers = [shipment[0]?.company];
      if (body?.employees) {
        for (const item of body?.employees) {
          if (item?.employee_id) {
            // @@start this is for when update shipment and employee id is given
            let findUser = await this.mapCompanyEmployeeModel.find({
              company_id: new mongoose.Types.ObjectId(shipment[0]?.company_id),
              employee_id: new mongoose.Types.ObjectId(item?.employee_id),
            });
            if (findUser?.length > 0) continue;
            await new this.mapCompanyEmployeeModel({
              company_id: new mongoose.Types.ObjectId(shipment[0]?.company_id),
              employee_id: new mongoose.Types.ObjectId(item?.employee_id),
              show_invoice: item?.show_invoice,
            }).save();

            // @@end this is for when update shipment and employee id is given
            continue;
          }

          const employee = await this.userModel.aggregate([
            {
              $match: {
                phone_number: item?.phone_number,
                country_phone_code: item?.country_phone_code,
                deleted_at: null,
              },
            },
            {
              $lookup: {
                from: 'map_user_devices',
                as: 'devices',
                localField: '_id',
                foreignField: 'user_id',
              },
            },
          ]);
          if (employee?.length === 0) {
            const newEmployee = await new this.userModel({
              phone_number: item?.phone_number,
              first_name: item?.first_name,
              last_name: item?.last_name,
              country_phone_code: item?.country_phone_code,
            }).save();
            await new this.mapCompanyEmployeeModel({
              company_id: new mongoose.Types.ObjectId(shipment[0]?.company_id),
              employee_id: new mongoose.Types.ObjectId(newEmployee?._id),
              show_invoice: item?.show_invoice,
            }).save();
            notificationUsers.push(newEmployee);
          } else {
            if (employee[0]?.is_company === false) {
              await new this.mapCompanyEmployeeModel({
                company_id: new mongoose.Types.ObjectId(
                  shipment[0]?.company_id,
                ),
                employee_id: new mongoose.Types.ObjectId(employee[0]?._id),
                show_invoice: item?.show_invoice,
              }).save();
              notificationUsers.push(employee[0]);
            }
          }
        }
      }

      const allPromises = [];
      /////////////Saving multiple commodities of this shipment/////////////
      if (body?.commodity) {
        for (let i = 0; i < body?.commodity?.length; i++) {
          if (body?.commodity[i]?.new && body?.commodity[i]?.name_en) {
            allPromises.push(() =>
              new this.mapShipmentCommodityModal({
                ...body?.commodity[i],
                shipment_id: new mongoose.Types.ObjectId(shipment[0]?._id),
              }).save(),
            );
          } else {
            allPromises.push(() =>
              this.mapShipmentCommodityModal.findByIdAndUpdate(
                body?.commodity[i]?._id,
                {
                  ...body?.commodity[i],
                  shipment_id: new mongoose.Types.ObjectId(shipment[0]?._id),
                },
              ),
            );
          }
        }
      }

      //////////////assign sipment new customer///////////////////
      if (notificationUsers[0]?.phone_number !== body?.phone_number) {
        const userExists = await this.userModel.findOne({
          phone_number: body?.phone_number,
          country_phone_code: body?.country_phone_code,
        });
        if (!userExists) {
          throw new BadRequestException(ErrorMsg?.USER_NOT_FOUND[lang || EN]);
        }
        // notificationUsers.push(userExists)
        console.log('userexists', userExists);
        await this.shipmentModel.findByIdAndUpdate(shipment_id, {
          company_id: userExists?._id,
        });
      }

      ////////////////////////Shipment Status/////////////////////
      // let newStatus;
      if (body?.shipment_status) {
        let status_en;
        let status_ar;
        if (lang === EN) {
          status_en = body?.shipment_status;
          status_ar = await translateData(body?.shipment_status, 'ar');
        } else {
          status_en = await translateData(body?.shipment_status, 'en');
          status_ar = body?.shipment_status;
        }
        ////////saving status////////
        const newStatus = await new this.mapShipmentStatusModel({
          status_en,
          status_ar,
          shipment_id: new mongoose.Types.ObjectId(shipment_id),
        }).save();
        body[CURRENT_STATUS_ID] = new mongoose.Types.ObjectId(newStatus?._id);
        if (notify) {
          for (const user of notificationUsers) {
            //////////////////////Device Tokens For Notifications/////////////////////
            const deviceTokens = [];
            for (const item of user?.devices) {
              deviceTokens.push(item?.device_token);
            }
            /////////////Sending Notifications///////////////
            allPromises.push(() =>
              this.sendShipmentStatusNotification(
                user,
                shipment_id,
                deviceTokens,
              ),
            );
          }
        }
      }

      ///////////////////////Shipment Mode////////////////////////
      let obj: any = {};
      if (body?.shipment_mode) {
        obj = {
          ...body,
          shipment_mode: new mongoose.Types.ObjectId(body?.shipment_mode),
        };
      }

      if (body?.serial_number) {
        const existing = await this.shipmentModel.findOne({
          serial_number: body.serial_number,
          _id: { $ne: shipment_id },
        });

        if (existing) {
          throw new BadRequestException(
            `Serial number ${body.serial_number} already exists. Please use a unique one.`,
          );
        }
        obj.serial_number = body.serial_number;
      }
      await this.shipmentModel.findByIdAndUpdate(shipment_id, obj);

      /////////saving file if given////////
      if (allFiles?.length > 0) {
        for (const file of allFiles) {
          allPromises.push(() =>
            new this.mapShipmentAttachmentModel({
              name: file?.fieldname,
              file_name: file?.filename,
              original_name: file?.originalname,
              mime_type: file?.mimetype,
              type: DOCUMENT,
              shipment_id: new mongoose.Types.ObjectId(shipment_id),
              path: file?.path,
              base_url: `${req.protocol}://${req.headers.host}/`,
              uploaded_by: ADMIN,
            }).save(),
          );
        }

        if (notify) {
          for (const user of notificationUsers) {
            if (user?.last_login) {
              //////////////////////Device Tokens For Notifications/////////////////////
              const deviceTokens = [];
              for (const item of user?.devices) {
                deviceTokens.push(item?.device_token);
              }

              // if (files?.shipment_document?.length > 0) {
              //   allPromises.push(() =>
              //     this.sendShipmentDocumentNotification(
              //       user,
              //       shipment_id,
              //       deviceTokens,
              //     ),
              //   );
              // } else {
              //   allPromises.push(() =>
              //     this.sendShipmentInvoiceNotification(
              //       user,
              //       shipment_id,
              //       deviceTokens,
              //     ),
              //   );
              // }

              if (files?.shipment_document?.length > 0) {
                allPromises.push(() =>
                  this.sendShipmentDocumentNotification(
                    user,
                    shipment_id,
                    deviceTokens,
                  ),
                );
              } else if (files?.shipment_invoice?.length > 0) {
                allPromises.push(() =>
                  this.sendShipmentInvoiceNotification(
                    user,
                    shipment_id,
                    deviceTokens,
                  ),
                );
              } else if (files?.receiving_slip?.length > 0) {
                allPromises.push(
                  () =>
                    this.sendReceivingSlipNotification(
                      user,
                      shipment_id,
                      deviceTokens,
                    ), // 👈 new method
                );
              }
            }
          }
        }
      }

      if (body?.removed_employees) {
        for (let i = 0; i < body?.removed_employees?.length; i++) {
          try {
            allPromises.push(() =>
              this.mapCompanyEmployeeModel.findOneAndDelete({
                company_id: new mongoose.Types.ObjectId(
                  shipment[0]?.company_id,
                ),
                employee_id: new mongoose.Types.ObjectId(
                  body?.removed_employees[i],
                ),
              }),
            );
          } catch (error) {
            continue;
          }
        }
      }

      if (body?.removed_commodity) {
        for (let i = 0; i < body?.removed_commodity?.length; i++) {
          try {
            allPromises.push(() =>
              this.mapShipmentCommodityModal.findByIdAndDelete(
                body?.removed_commodity[i],
              ),
            );
          } catch (error) {
            continue;
          }
        }
      }
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.SHIPMENT_UPDATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************GET SINGLE SHIPMENT***********************************/
  async getSingleShipment(lang: string, shipment_id: string, res: Response) {
    try {
      const shipment = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$user',
          },
        },
        {
          $lookup: {
            from: 'shipment_modes',
            as: 'shipment_mode',
            let: { mode_id: '$shipment_mode' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$mode_id'],
                  },
                },
              },
            ],
          },
        },
        {
          $unwind: { path: '$shipment_mode', preserveNullAndEmptyArrays: true },
        },
        {
          $lookup: {
            from: 'map_shipment_statuses',
            as: 'shipment_status',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$shipment_id', '$$shipment_id'],
                  },
                },
              },
              // {
              //   $project: {
              //     status: '$status_en',
              //     createdAt: 1,
              //     date: 1,
              //   },
              // },
              {
                $sort: {
                  createdAt: -1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'shipment_attachments',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$shipment_id', '$$shipment_id'],
                  },
                  name: 'shipment_document',
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'shipment_invoice',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$shipment_id', '$$shipment_id'],
                  },
                  name: 'shipment_invoice',
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'receiving_slip',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
                  name: 'receiving_slip',
                },
              },
              { $sort: { createdAt: -1 } },
              {
                $project: {
                  // _id: 0,
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'barcode',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: { $eq: ['$shipment_id', '$$shipment_id'] },
                  name: 'barcode',
                },
              },
              { $sort: { createdAt: -1 } },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_commodities',
            as: 'commodity',
            localField: '_id',
            foreignField: 'shipment_id',
          },
        },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'company_employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: {
                  path: '$company_employee',
                },
              },
              {
                $project: {
                  first_name: '$company_employee.first_name',
                  last_name: '$company_employee.last_name',
                  phone_number: '$company_employee.phone_number',
                  country_phone_code: '$company_employee.country_phone_code',
                  _id: 0,
                  employee_id: '$company_employee._id',
                  show_invoice: 1,
                  verification_code: 1,
                  is_verified: 1,
                },
              },
            ],
          },
        },
      ]);
      if (!shipment[0]) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data: shipment[0],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************DELETE SHIPMENT***************************************/
  async deleteShipment(lang: string, shipment_id: string, res: Response) {
    try {
      const shipment = await this.shipmentModel.aggregate([
        { $match: { _id: new mongoose.Types.ObjectId(shipment_id) } },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'attachments',
            localField: '_id',
            foreignField: 'shipment_id',
          },
        },
      ]);
      if (!shipment[0]) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }
      const promiseArr = [];
      promiseArr.push(() => this.shipmentModel.findByIdAndDelete(shipment_id));
      promiseArr.push(() =>
        this.mapShipmentAttachmentModel.deleteMany({
          shipment_id: new mongoose.Types.ObjectId(shipment_id),
        }),
      );
      promiseArr.push(() =>
        this.mapShipmentStatusModel.deleteMany({
          shipment_id: new mongoose.Types.ObjectId(shipment_id),
        }),
      );
      promiseArr.push(() =>
        this.notificationModel.deleteMany({
          shipment_id: new mongoose.Types.ObjectId(shipment_id),
        }),
      );
      promiseArr.push(() =>
        this.mapShipmentCommodityModal.deleteMany({
          shipment_id: new mongoose.Types.ObjectId(shipment_id),
        }),
      );
      const resolved = promiseArr.map((item) => item());
      await Promise.allSettled(resolved);
      ////////////deleting file from local storage if exists/////////
      for (const data of shipment[0]?.attachments) {
        if (fs.existsSync(data?.path)) {
          fs.unlink(data?.path, (err) => {
            if (err) console.log('not found');
            else console.log('deleted');
          });
        } else {
          console.log('not found');
        }
      }
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        message: SuccessMsg?.SHIPMENT_DELETED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************UPLOAD SHIPMENT DOCUMENT*************************************/
  async uploadShipmentDocument(
    req: Request,
    lang: string,
    shipment_id: string,
    notify: boolean,
    files: { shipment_document?: Express.Multer.File[] },
    res: Response,
  ) {
    try {
      if (req['fileValidationError']) {
        throw new BadRequestException(req['fileValidationError']);
      }
      if (!files?.shipment_document?.length) {
        throw new BadRequestException(
          ErrorMsg?.PROVIDE_VALID_DOCUMENT[lang || EN],
        );
      }
      /////////////////Shipment Data////////////////////
      const shipment = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);
      if (shipment.length === 0) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }

      //////////if shipment is completed///////////
      if (shipment[0]?.current_state === COMPLETED) {
        throw new BadRequestException(ErrorMsg?.CANT_ADD_DOCUMENT[lang || EN]);
      }

      ///////////////User Devices/////////////
      const notificationUsers = [
        shipment[0]?.company,
        ...shipment[0]?.company_employees,
      ];
      const allPromises = [];
      ///////////Shipment Attachments////////////
      for (const file of files?.shipment_document) {
        allPromises.push(() =>
          new this.mapShipmentAttachmentModel({
            name: file?.fieldname,
            file_name: file?.filename,
            original_name: file?.originalname,
            mime_type: file?.mimetype,
            type: DOCUMENT,
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
            path: file?.path,
            base_url: `${req.protocol}://${req.headers.host}/`,
            uploaded_by: ADMIN,
          }).save(),
        );
      }

      if (notify) {
        /////////sending firebase push notifications/////////
        for (const user of notificationUsers) {
          ////////////////////Sending Notification///////////////////
          allPromises.push(() =>
            this.sendShipmentDocumentNotification(
              user,
              shipment_id,
              user?.devices,
            ),
          );
        }
      }
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.DOCUMENT_UPLOADED[lang ?? EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************UPLOAD SHIPMENT DOCUMENT*************************************/
  async uploadReceivingSlip(
    req: Request,
    lang: string,
    shipment_id: string,
    notify: boolean,
    files: { receiving_slip?: Express.Multer.File[] },
    res: Response,
  ) {
    try {
      if (req['fileValidationError']) {
        throw new BadRequestException(req['fileValidationError']);
      }
      if (!files?.receiving_slip?.length) {
        throw new BadRequestException(
          ErrorMsg?.PROVIDE_VALID_DOCUMENT[lang || EN],
        );
      }
      /////////////////Shipment Data////////////////////
      const shipment = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);
      if (shipment.length === 0) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }

      //////////if shipment is completed///////////
      if (shipment[0]?.current_state === COMPLETED) {
        throw new BadRequestException(ErrorMsg?.CANT_ADD_DOCUMENT[lang || EN]);
      }

      ///////////////User Devices/////////////
      const notificationUsers = [
        shipment[0]?.company,
        ...shipment[0]?.company_employees,
      ];
      const allPromises = [];
      ///////////Shipment Attachments////////////
      for (const file of files?.receiving_slip) {
        allPromises.push(() =>
          new this.mapShipmentAttachmentModel({
            name: file?.fieldname,
            file_name: file?.filename,
            original_name: file?.originalname,
            mime_type: file?.mimetype,
            type: DOCUMENT,
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
            path: file?.path,
            base_url: `${req.protocol}://${req.headers.host}/`,
            uploaded_by: ADMIN,
          }).save(),
        );
      }

      if (notify) {
        /////////sending firebase push notifications/////////
        for (const user of notificationUsers) {
          ////////////////////Sending Notification///////////////////
          allPromises.push(() =>
            this.sendShipmentDocumentNotification(
              user,
              shipment_id,
              user?.devices,
            ),
          );
        }
      }
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.RECEIVINGSLIP_UPLOADED[lang ?? EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************UPLOAD SHIPMENT INVOICE**************************************/
  async uploadShipmentInvoice(
    req: Request,
    lang: string,
    shipment_id: string,
    notify: boolean,
    files: { shipment_invoice?: Express.Multer.File[] },
    res: Response,
  ) {
    try {
      if (req['fileValidationError']) {
        throw new BadRequestException(req['fileValidationError']);
      }
      if (!files?.shipment_invoice?.length) {
        throw new BadRequestException(
          ErrorMsg?.PROVIDE_VALID_DOCUMENT[lang || EN],
        );
      }
      const shipment = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $and: [
                      { $eq: ['$company_id', '$$company_id'] },
                      { $eq: ['$show_invoice', true] },
                    ],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);

      if (shipment.length === 0) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }

      //////////if shipment is completed///////////
      if (shipment[0]?.current_state === COMPLETED) {
        throw new BadRequestException(ErrorMsg?.CANT_ADD_DOCUMENT[lang || EN]);
      }

      ///////////////User Devices/////////////
      const notificationUsers = [
        shipment[0]?.company,
        ...shipment[0]?.company_employees,
      ];

      const allPromises = [];
      //////////////Saving File Data/////////////
      for (const file of files?.shipment_invoice) {
        allPromises.push(() =>
          new this.mapShipmentAttachmentModel({
            name: file?.fieldname,
            file_name: file?.filename,
            original_name: file?.originalname,
            mime_type: file?.mimetype,
            type: DOCUMENT,
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
            path: file?.path,
            base_url: `${req.protocol}://${req.headers.host}/`,
            uploaded_by: ADMIN,
          }).save(),
        );
      }
      if (notify) {
        for (const user of notificationUsers) {
          ////////////////////Sending Notification///////////////////
          allPromises.push(() =>
            this.sendShipmentInvoiceNotification(
              user,
              shipment_id,
              user?.devices,
            ),
          );
        }
      }
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.INVOICE_UPLOADED[lang ?? EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************DELETE SINGLE SHIPMENT DOCUMENT******************************/
  async deleteShipmentDocument(lang: string, doc_id: string, res: Response) {
    try {
      const data = await this.mapShipmentAttachmentModel.findById(doc_id);
      /////////deleting from local storage/////////
      if (fs.existsSync(data?.path)) {
        fs.unlink(data?.path, (err) => {
          if (err) console.log('not found');
          else console.log('deleted');
        });
      } else {
        console.log('not found');
      }
      await this.mapShipmentAttachmentModel.findByIdAndDelete(doc_id);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        message: SuccessMsg?.DOCUMENT_DELETED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*************************DELETE SINGLE SHIPMENT DOCUMENT******************************/
  async deleteReceivingSlip(lang: string, doc_id: string, res: Response) {
    try {
      const data = await this.mapShipmentAttachmentModel.findById(doc_id);
      /////////deleting from local storage/////////
      if (fs.existsSync(data?.path)) {
        fs.unlink(data?.path, (err) => {
          if (err) console.log('not found');
          else console.log('deleted');
        });
      } else {
        console.log('not found');
      }
      await this.mapShipmentAttachmentModel.findByIdAndDelete(doc_id);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        message: SuccessMsg?.DOCUMENT_DELETED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************ADD SHIPMENT STATUS***********************************/
  async addShipmentStatus(
    lang: string,
    shipment_id: string,
    notify: boolean,
    body: AddStatusDto,
    res: Response,
  ) {
    try {
      const shipment = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);

      if (shipment.length === 0) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }
      /////////if completed can't add status/////////
      if (shipment[0]?.current_state === COMPLETED) {
        throw new BadRequestException(ErrorMsg?.CANT_ADD_STATUS[lang || EN]);
      }

      ///////////////User Devices/////////////
      const notificationUsers = [
        shipment[0]?.company,
        ...shipment[0]?.company_employees,
      ];

      let status_en;
      let status_ar;
      if (lang === EN) {
        status_en = body?.status;
        status_ar = await translateData(body?.status, 'ar');
      } else {
        status_en = await translateData(body?.status, 'en');
        status_ar = body?.status;
      }
      const newStatus = await new this.mapShipmentStatusModel({
        status_en,
        status_ar,
        shipment_id: new mongoose.Types.ObjectId(shipment_id),
      }).save();

      await this.shipmentModel.findByIdAndUpdate(shipment_id, {
        $set: {
          current_status_id: new mongoose.Types.ObjectId(newStatus?._id),
        },
      });
      ////////////sending notfications//////////
      if (notify) {
        const promiseArr = notificationUsers.map((user) =>
          this.sendShipmentStatusNotification(user, shipment_id, user?.devices),
        );
        await Promise.allSettled(promiseArr);
      }
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.STATUS_UPDATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************ADD MULTI SHIPMENT STATUS***********************************/
  async addMultiShipmentStatus(
    lang: string,
    notify: boolean,
    body: AddMultiStatusDto,
    res: Response,
  ) {
    try {
      const { shipment_ids, status } = body;

      console.log('_shipment_ids', shipment_ids, status, notify);
      if (!shipment_ids || shipment_ids.length === 0) {
        throw new CustomException('No shipment IDs provided.', 400);
      }

      const promises = shipment_ids.map(async (shipment_id) => {
        try {
          await this.addShipmentStatus(
            lang,
            shipment_id,
            notify,
            { status },
            res,
          );
          return {
            shipment_id,
            success: true,
            message: `Status '${status}' added.`,
          };
        } catch (err) {
          return { shipment_id, success: false, message: err?.message };
        }
      });

      const results = await Promise.allSettled(promises);

      // ✅ Return combined response
      return res.status(200).json({
        success: true,
        message: `Status '${status}' processed for ${shipment_ids.length} shipments.`,
        results,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  /*------------------------------------------------------------------------------------*/

  /********************************UPDATE SHIPMENT STATUS********************************/
  async updateShipmentStatus(
    lang: string,
    status_id: string,
    body: AddStatusDto,
    res: Response,
  ) {
    try {
      let status_en;
      let status_ar;
      if (lang === EN) {
        status_en = body?.status;
        status_ar = await translateData(body?.status, 'ar');
      } else {
        status_en = await translateData(body?.status, 'en');
        status_ar = body?.status;
      }
      await this.mapShipmentStatusModel.findByIdAndUpdate(status_id, {
        status_en,
        status_ar,
        date: new Date(body?.date),
      });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        message: SuccessMsg?.STATUS_UPDATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************GET ALL SHIPMENT MODES********************************/
  async getAllShipmentModes(page = 1, limit = 10, search = '', res: Response) {
    try {
      const data = await this.shipmentModeModel.find({
        $or: [
          { name_en: { $regex: `.*${search}.*`, $options: 'i' } },
          { slug: { $regex: `.*${search}.*`, $options: 'i' } },
          { name_ar: { $regex: `.*${search}.*`, $options: 'i' } },
        ],
      });
      const total = await this.shipmentModeModel.countDocuments({
        $or: [
          { name_en: { $regex: `.*${search}.*`, $options: 'i' } },
          { slug: { $regex: `.*${search}.*`, $options: 'i' } },
          { name_ar: { $regex: `.*${search}.*`, $options: 'i' } },
        ],
      });
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        current_page: Number(page),
        total_pages: Math.ceil(Number(total) / Number(limit)) || 0,
        limit: Number(limit),
        total: Number(total),
        data,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************DELETE SHIPMENT MODE**********************************/
  async deleteShipmentMode(
    lang: string,
    shipment_mode_id: string,
    res: Response,
  ) {
    try {
      await this.shipmentModeModel.findByIdAndDelete(shipment_mode_id);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        message: SuccessMsg?.SHIPMENT_MODE_DELETED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************GET ALL USERS*****************************************/
  async getAllUsers(page = 1, limit = 10, search = '', res: Response) {
    try {
      const data = await this.userModel.aggregate([
        {
          $addFields: {
            full_name: { $concat: ['$first_name', ' ', '$last_name'] },
          },
        },
        // {
        //   $match: {
        //     $or: [
        //       { full_name: { $regex: `.*${search}.*`, $options: 'i' } },
        //       { phone_number: { $regex: `.*${search}.*`, $options: 'i' } },
        //       { username: { $regex: `.*${search}.*`, $options: 'i' } },
        //       { country: { $regex: `.*${search}.*`, $options: 'i' } },
        //       { city: { $regex: `.*${search}.*`, $options: 'i' } },
        //     ],
        //     last_login: { $ne: null },
        //   },
        // },
        {
          $match: {
            $and: [
              {
                $or: [
                  { full_name: { $regex: `.*${search}.*`, $options: 'i' } },
                  { phone_number: { $regex: `.*${search}.*`, $options: 'i' } },
                  { username: { $regex: `.*${search}.*`, $options: 'i' } },
                  { country: { $regex: `.*${search}.*`, $options: 'i' } },
                  { city: { $regex: `.*${search}.*`, $options: 'i' } },
                ],
              },
              {
                $or: [
                  { last_login: { $ne: null } }, // user has logged in
                  { created_by: 'admin' }, // OR created by admin
                ],
              },
            ],
          },
        },
        {
          $project: {
            full_name: 1,
            username: 1,
            phone_number: 1,
            country_phone_code: 1,
            city: 1,
            country: 1,
            createdAt: 1,
            is_blocked: 1,
            phone_number_verified_at: 1,
            is_admin: 1,
          },
        },
        {
          $facet: {
            paginatedResults: [
              { $sort: { phone_number_verified_at: -1 } },
              { $skip: (Number(page) - 1) * Number(limit) },
              { $limit: Number(limit) },
            ],
            totalCount: [{ $count: 'count' }],
          },
        },
        {
          $addFields: {
            total: {
              $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
            },
          },
        },
        {
          $project: {
            paginatedResults: 1,
            total: 1,
          },
        },
      ]);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        current_page: Number(page),
        total_pages: Math.ceil(Number(data[0].total) / Number(limit)) || 0,
        limit: Number(limit),
        total: Number(data[0].total),
        data: data[0].paginatedResults,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************BLOCK UNBLOCK USER************************************/
  async changeUserStatus(lang: string, user_id: string, res: Response) {
    try {
      const user = await this.userModel.findById(user_id);
      if (!user) {
        throw new BadRequestException(ErrorMsg?.USER_NOT_FOUND[lang || EN]);
      }
      ////////if blocked then unblocking else blocking/////////
      await this.userModel.findByIdAndUpdate(user_id, {
        is_blocked: user?.is_blocked ? false : true,
      });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: user?.is_blocked
          ? SuccessMsg?.USER_UNBLOCKED[lang || EN]
          : SuccessMsg?.USER_BLOCKED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************TRANSLATE*****************************************/
  async translateKeyword(
    lang: string,
    translate_to: string,
    keyword: string,
    res: Response,
  ) {
    try {
      if (!keyword) {
        return res.status(HttpStatus.OK).json({
          success: true,
          statusCode: 200,
          data: '',
        });
      }
      const data = await translateData(keyword, translate_to);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data,
      });
    } catch (error) {
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data: keyword,
      });
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************GET ALL INQUIRIES*********************************/
  async getAllInquiry(
    lang: string,
    status = '',
    page = 1,
    limit = 10,
    search = '',
    res: Response,
  ) {
    try {
      const query = {};
      if (status === 'true') {
        query[STATUS] = true;
      } else if (status === 'false') {
        query[STATUS] = false;
      }

      // const data = await this.inquiryModel.aggregate([
      //   {
      //     $lookup: {
      //       from: 'users',
      //       as: 'user',
      //       let: { user_id: '$user_id' },
      //       pipeline: [
      //         {
      //           $match: {
      //             $expr: {
      //               $eq: ['$_id', '$$user_id'],
      //             },
      //           },
      //         },
      //         {
      //           $project: {
      //             name: { $concat: ['$first_name', ' ', '$last_name'] },
      //             username: 1,
      //             phone_number: 1,
      //           },
      //         },
      //       ],
      //     },
      //   },
      //   {
      //     $unwind: { path: '$user' },
      //   },
      //   {
      //     $match: {
      //       ...query,
      //       $or: [
      //         { inquiry: { $regex: `.*${search}.*`, $options: 'i' } },
      //         { equipments: { $regex: `.*${search}.*`, $options: 'i' } },
      //         { 'user.name': { $regex: `.*${search}.*`, $options: 'i' } },
      //         { commodity: { $regex: `.*${search}.*`, $options: 'i' } },
      //         {
      //           pickup: {
      //             $regex: `.*${search}.*`,
      //             $options: 'i',
      //           },
      //         },
      //         {
      //           delivery: {
      //             $regex: `.*${search}.*`,
      //             $options: 'i',
      //           },
      //         },
      //       ],
      //     },
      //   },
      //   {
      //     $facet: {
      //       paginatedResults: [
      //         { $sort: { createdAt: -1 } },
      //         { $skip: (Number(page) - 1) * Number(limit) },
      //         { $limit: Number(limit) },
      //       ],
      //       totalCount: [{ $count: 'count' }],
      //     },
      //   },
      //   {
      //     $addFields: {
      //       total: {
      //         $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
      //       },
      //     },
      //   },
      //   {
      //     $project: {
      //       paginatedResults: 1,
      //       total: 1,
      //     },
      //   },
      // ]);
      const data = await this.inquiryModel.aggregate([
        {
          $match: {
            ...query,
            $or: [
              { inquiry: { $regex: search, $options: 'i' } },
              { equipments: { $regex: search, $options: 'i' } },
              { commodity: { $regex: search, $options: 'i' } },
              { pickup: { $regex: search, $options: 'i' } },
              { delivery: { $regex: search, $options: 'i' } },
            ],
          },
        },
        {
          $lookup: {
            from: 'quotations',
            localField: '_id',
            foreignField: 'inquiry_id',
            as: 'quotations',
          },
        },
        { $unwind: { path: '$quotations', preserveNullAndEmptyArrays: true } },
        { $sort: { createdAt: -1 } },
        { $skip: (Number(page) - 1) * Number(limit) },
        { $limit: Number(limit) },
      ]);
      const total = await this.inquiryModel.countDocuments({
        ...query,
        $or: [
          { inquiry: { $regex: `.*${search}.*`, $options: 'i' } },
          { equipments: { $regex: `.*${search}.*`, $options: 'i' } },
          { 'user.name': { $regex: `.*${search}.*`, $options: 'i' } },
          { commodity: { $regex: `.*${search}.*`, $options: 'i' } },
          {
            pickup: {
              $regex: `.*${search}.*`,
              $options: 'i',
            },
          },
          {
            delivery: {
              $regex: `.*${search}.*`,
              $options: 'i',
            },
          },
        ],
      });
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        current_page: Number(page),
        total_pages: Math.ceil(Number(total) / Number(limit)) || 0,
        limit: Number(limit),
        total: Number(total),
        data,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************GET SINGLE INQUIRY********************************/
  async getSingleInquiry(lang: string, inquiry_id: string, res: Response) {
    try {
      const data = await this.inquiryModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(inquiry_id),
          },
        },
        // {
        //   $lookup: {
        //     from: 'users',
        //     as: 'user',
        //     let: { user_id: '$user_id' },
        //     pipeline: [
        //       {
        //         $match: {
        //           $expr: {
        //             $eq: ['$_id', '$$user_id'],
        //           },
        //         },
        //       },
        //       {
        //         $project: {
        //           name: { $concat: ['$first_name', ' ', '$last_name'] },
        //           username: 1,
        //           phone_number: 1,
        //         },
        //       },
        //     ],
        //   },
        // },
        // {
        //   $unwind: { path: '$user' },
        // },
        {
          $lookup: {
            from: 'map_inquiry_attachments',
            as: 'quotations',
            let: { inquiry_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$inquiry_id', '$$inquiry_id'],
                  },
                },
              },
              {
                $project: {
                  document: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_inquiry_replies',
            as: 'replies',
            let: { inquiry_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$inquiry_id', '$$inquiry_id'],
                  },
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
            ],
          },
        },
        // {
        //   $lookup:{
        //   from:'quotations',
        //   localField:"_id",
        //   foreignField:"inquiry_id",
        //   as:"quotationDetails"
        //   }
        // },
        // {
        //   $unwind:{path:"$quotationDetails", preserveNullAndEmptyArrays: true}
        // }
      ]);
      if (!data[0]) {
        throw new BadRequestException(ErrorMsg?.INQUIRY_NOT_FOUND[lang || EN]);
      }
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data: data[0],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************RESOLVE INQUIRY***********************************/
  async resolveInquiry(lang: string, inquiry_id: string, res: Response) {
    try {
      const inquiry = await this.inquiryModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(inquiry_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$user_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  let: { user_id: '$_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: { $eq: ['$user_id', '$$user_id'] },
                      },
                    },
                  ],
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$user',
          },
        },
      ]);

      if (inquiry?.length === 0) {
        throw new BadRequestException(ErrorMsg?.INQUIRY_NOT_FOUND[lang || EN]);
      }
      ///////////sending notifications//////////
      const deviceTokens = [];
      for (let i = 0; i < inquiry[0]?.user?.devices.length; i++) {
        deviceTokens.push(inquiry[0]?.user?.devices[i]?.device_token);
      }
      const allPromises = [];
      allPromises.push(() =>
        new this.notificationModel({
          inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
          user_id: new mongoose.Types.ObjectId(inquiry[0]?.user_id),
          title_en: NotificationMessages?.INQUIRY_RESOLVED?.TITLE?.EN,
          title_ar: NotificationMessages?.INQUIRY_RESOLVED?.TITLE?.AR,
          body_en: NotificationMessages?.INQUIRY_RESOLVED?.BODY?.EN,
          body_ar: NotificationMessages?.INQUIRY_RESOLVED?.BODY?.AR,
        }).save(),
      );
      allPromises.push(() =>
        this.sendFirbaseNotificationService.sendToDevice(
          NotificationMessages?.INQUIRY_RESOLVED?.TITLE[
            inquiry[0]?.user[LANG] || EN
          ],
          NotificationMessages?.INQUIRY_RESOLVED?.BODY[
            inquiry[0]?.user[LANG] || EN
          ],
          deviceTokens,
          { user_id: inquiry[0]?.user_id?.toString(), inquiry_id },
        ),
      );
      allPromises.push(() =>
        this.inquiryModel.findByIdAndUpdate(inquiry_id, { status: true }),
      );
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.INQUIRY_RESOLVED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************DELETE INQUIRY************************************/
  async deleteInquiry(lang: string, inquiry_id: string, res: Response) {
    try {
      const inquiry = await this.inquiryModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(inquiry_id),
          },
        },
        {
          $lookup: {
            from: 'map_inquiry_attachments',
            as: 'attachments',
            localField: '_id',
            foreignField: 'inquiry_id',
          },
        },
      ]);
      if (!inquiry[0]) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }
      await this.mapInquiryAttachmentModel.deleteMany({
        inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
      });
      await this.mapInquiryReplyModel.deleteMany({
        inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
      });
      await this.notificationModel.deleteMany({
        inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
      });
      ////////////deleting file from local storage if exists/////////
      if (inquiry[0]?.attachments?.length) {
        for (const data of inquiry[0]?.attachments) {
          if (fs.existsSync(data?.path)) {
            fs.unlink(data?.path, (err) => {
              if (err) console.log('not found');
              else console.log('deleted');
            });
          } else {
            console.log('not found');
          }
        }
      }
      await this.inquiryModel.findByIdAndDelete(inquiry_id);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        message: SuccessMsg?.INQUIRY_DELETED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************GET USERS OPTIONS*********************************/
  async getUsersOptions(lang: string, type: string, res: Response) {
    try {
      const query: Record<string, any> = { deleted_at: null };

      if (type === COMPANY) {
        query[IS_COMPANY] = true;
      } else {
        query[IS_COMPANY] = false;
      }
      const users = await this.userModel.find(query);
      const data = users.map((item) => {
        return { label: capitalizeFull(item?.first_name), value: item?._id };
      });
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************GET SINGLE USER***********************************/
  async getSingleUser(user_id: string, res: Response) {
    try {
      // const data = await this.userModel.findById(user_id).select({
      //   first_name: 1,
      //   last_name: 1,
      //   phone_number: 1,
      //   company_name: 1,
      //   country_phone_code: 1,
      // });
      // let employees = [];
      // if (data?.company_name) {
      //   employees = await this.mapCompanyEmployeeModel.aggregate([
      //     { $match: { company_id: new mongoose.Types.ObjectId(user_id) } },
      //     {
      //       $lookup: {
      //         from: 'users',
      //         as: 'employee',
      //         let: { employee_id: '$employee_id' },
      //         pipeline: [
      //           { $match: { $expr: { $eq: ['$_id', '$$employee_id'] } } },
      //           {
      //             $project: {
      //               first_name: 1,
      //               last_name: 1,
      //               phone_number: 1,
      //               employee_id: '$_id',
      //               _id: 0,
      //               country_phone_code: 1,
      //             },
      //           },
      //         ],
      //       },
      //     },
      //     {
      //       $unwind: {
      //         path: '$employee',
      //       },
      //     },
      //     {
      //       $project: {
      //         first_name: '$employee.first_name',
      //         last_name: '$employee.last_name',
      //         phone_number: '$employee.phone_number',
      //         employee_id: '$employee.employee_id',
      //         country_phone_code: '$employee.country_phone_code',
      //         _id: 0,
      //         show_invoice: '$show_invoice',
      //       },
      //     },
      //   ]);
      // }
      // if (data['_doc']?.first_name) {
      //   data['_doc'].first_name = capitalizeFull(data['_doc']?.first_name);
      //   data['_doc'].last_name = capitalizeFull(data['_doc']?.last_name);
      //   data['_doc'].company_name = capitalizeFull(data['_doc']?.company_name);
      //   if (employees?.length > 0) {
      //     for (const item in employees) {
      //       employees[item].first_name = capitalizeFull(
      //         employees[item]?.first_name,
      //       );
      //       employees[item].last_name = capitalizeFull(
      //         employees[item]?.last_name || '',
      //       );
      //     }
      //   }
      // }
      const data = await this.userModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(user_id),
          },
        },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'employees',
            let: { company_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  localField: 'employee_id',
                  foreignField: '_id',
                },
              },
              {
                $unwind: '$employee',
              },
              {
                $project: {
                  first_name: '$employee.first_name',
                  last_name: '$employee.last_name',
                  phone_number: '$employee.phone_number',
                  employee_id: '$employee._id',
                  country_phone_code: '$employee.country_phone_code',
                  _id: 0,
                  show_invoice: '$show_invoice',
                },
              },
            ],
          },
        },
        {
          $project: {
            first_name: 1,
            last_name: 1,
            phone_number: 1,
            company_name: 1,
            country_phone_code: 1,
            employees: 1,
          },
        },
      ]);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data: data[0],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************************REPLY INQUIRY*************************************/
  async replyInquiry(
    inquiry_id: string,
    notify: boolean,
    lang: string,
    body: ReplyInquiryDto,
    res: Response,
  ) {
    try {
      const inquiry = await this.inquiryModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(inquiry_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$user_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  let: { user_id: '$_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: { $eq: ['$user_id', '$$user_id'] },
                      },
                    },
                  ],
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$user',
          },
        },
      ]);

      if (inquiry.length === 0) {
        throw new BadRequestException(ErrorMsg?.INQUIRY_NOT_FOUND[lang || EN]);
      }
      await new this.mapInquiryReplyModel({
        inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
        message: body?.message,
      }).save();

      if (notify) {
        const allPromises = [];
        const deviceTokens = [];
        for (let i = 0; i < inquiry[0]?.user?.devices.length; i++) {
          deviceTokens.push(inquiry[0]?.user?.devices[i]?.device_token);
        }
        allPromises.push(() =>
          new this.notificationModel({
            user_id: inquiry[0]?.user_id,
            inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
            title_en: NotificationMessages?.INQUIRY_REPLIED?.TITLE?.EN,
            title_ar: NotificationMessages?.INQUIRY_REPLIED?.TITLE?.AR,
            body_en: NotificationMessages?.INQUIRY_REPLIED?.BODY?.EN,
            body_ar: NotificationMessages?.INQUIRY_REPLIED?.BODY?.AR,
          }).save(),
        );
        allPromises.push(() =>
          this.sendFirbaseNotificationService.sendToDevice(
            NotificationMessages?.INQUIRY_REPLIED?.TITLE[
              inquiry[0]?.user[LANG] || EN
            ],
            NotificationMessages?.INQUIRY_REPLIED?.BODY[
              inquiry[0]?.user[LANG] || EN
            ],
            deviceTokens,
            { user_id: inquiry[0]?.user_id?.toString(), inquiry_id },
          ),
        );
        const resolved = allPromises.map((item) => item());
        await Promise.allSettled(resolved);
      }
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.INQUIRY_REPLIED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  async completeMultipleShipments(
    shipment_ids: string[],
    lang: string,
    res: Response,
  ) {
    try {
      if (!shipment_ids || shipment_ids.length === 0) {
        throw new BadRequestException('Invalid shipment ids');
      }
      const objectIds = shipment_ids.map(
        (id) => new mongoose.Types.ObjectId(id),
      );
      const shipments = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: { $in: objectIds },
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              { $match: { $expr: { $eq: ['$_id', '$$user_id'] } } },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: { $expr: { $eq: ['$company_id', '$$company_id'] } },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: { $expr: { $eq: ['$_id', '$$employee_id'] } },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              { $unwind: { path: '$employee' } },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);

      if (shipments.length === 0) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }

      const allPromises = [];

      for (const shipment of shipments) {
        const notificationUsers = [
          shipment.company,
          ...shipment.company_employees,
        ];

        // Mark shipment as completed
        allPromises.push(
          this.shipmentModel.findByIdAndUpdate(shipment._id, {
            current_state: COMPLETED,
            is_verified: true,
          }),
        );

        // Notifications
        for (const user of notificationUsers) {
          allPromises.push(
            new this.notificationModel({
              user_id: new mongoose.Types.ObjectId(user?._id),
              shipment_id: shipment._id,
              title_en: NotificationMessages?.SHIPMENT_COMPLETED?.TITLE?.EN,
              title_ar: NotificationMessages?.SHIPMENT_COMPLETED?.TITLE?.AR,
              body_en: NotificationMessages?.SHIPMENT_COMPLETED?.BODY?.EN,
              body_ar: NotificationMessages?.SHIPMENT_COMPLETED?.BODY?.AR,
            }).save(),
          );

          if (user?.last_login) {
            this.sendFirbaseNotificationService.sendToDevice(
              NotificationMessages?.SHIPMENT_COMPLETED?.TITLE[user[LANG] || EN],
              NotificationMessages?.SHIPMENT_COMPLETED?.BODY[user[LANG] || EN],
              user?.devices,
              { user_id: user?._id?.toString(), shipment_id: shipment._id },
            );
          }
        }
      }

      await Promise.allSettled(allPromises);

      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.SHIPMENT_UPDATED[lang || EN],
        total_shipments: shipments.length,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  /*****************************ADD QUOTATION DOCUMENT***********************************/
  async addQuotationDocument(
    req: Request,
    inquiry_id: string,
    notify: boolean,
    lang: string,
    file: Express.Multer.File,
    res: Response,
  ) {
    try {
      if (req['fileValidationError']) {
        throw new BadRequestException(req['fileValidationError']);
      }
      if (!file) {
        throw new BadRequestException(
          ErrorMsg?.PROVIDE_VALID_DOCUMENT[lang || EN],
        );
      }
      const inquiry = await this.inquiryModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(inquiry_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$user_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  let: { user_id: '$_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: { $eq: ['$user_id', '$$user_id'] },
                      },
                    },
                  ],
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$user',
          },
        },
      ]);

      if (inquiry.length === 0) {
        throw new BadRequestException(ErrorMsg?.INQUIRY_NOT_FOUND[lang || EN]);
      }
      ///////////saving file in inquiry attachments//////////
      await new this.mapInquiryAttachmentModel({
        name: file?.fieldname,
        file_name: file?.filename,
        original_name: file?.originalname,
        mime_type: file?.mimetype,
        type: DOCUMENT,
        inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
        path: file?.path,
        base_url: `${req.protocol}://${req.headers.host}/`,
        uploaded_by: ADMIN,
      }).save();

      if (notify) {
        ////////////sending notifications using fcm token////////////
        const deviceTokens = [];
        for (let i = 0; i < inquiry[0]?.user?.devices.length; i++) {
          deviceTokens.push(inquiry[0]?.user?.devices[i]?.device_token);
        }
        await new this.notificationModel({
          user_id: inquiry[0]?.user_id,
          inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
          title_en: NotificationMessages?.QUOTATION_UPLOADED?.TITLE?.EN,
          title_ar: NotificationMessages?.QUOTATION_UPLOADED?.TITLE?.AR,
          body_en: NotificationMessages?.QUOTATION_UPLOADED?.BODY?.EN,
          body_ar: NotificationMessages?.QUOTATION_UPLOADED?.BODY?.AR,
        }).save();
        await this.sendFirbaseNotificationService.sendToDevice(
          NotificationMessages?.QUOTATION_UPLOADED?.TITLE[
            inquiry[0]?.user[LANG] || EN
          ],
          NotificationMessages?.QUOTATION_UPLOADED?.BODY[
            inquiry[0]?.user[LANG] || EN
          ],
          deviceTokens,
          { user_id: inquiry[0]?.user_id?.toString(), inquiry_id },
        );
      }

      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.QUOTATION_UPLOADED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*****************************COMPLETE SHIPMENT****************************************/
  async completeShipment(shipment_id: string, lang: string, res: Response) {
    try {
      const shipment = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);

      if (shipment.length === 0) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }
      /////////////////User Devices/////////////
      const notificationUsers = [
        shipment[0]?.company,
        ...shipment[0]?.company_employees,
      ];

      ////////completing shipment//////////
      await this.shipmentModel.findByIdAndUpdate(shipment_id, {
        current_state: COMPLETED,
        is_verified: true,
      });
      const allPromises = [];
      for (const user of notificationUsers) {
        ///////////////////In App Notifications/////////////
        allPromises.push(() =>
          new this.notificationModel({
            user_id: new mongoose.Types.ObjectId(user?._id),
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
            title_en: NotificationMessages?.SHIPMENT_COMPLETED?.TITLE?.EN,
            title_ar: NotificationMessages?.SHIPMENT_COMPLETED?.TITLE?.AR,
            body_en: NotificationMessages?.SHIPMENT_COMPLETED?.BODY?.EN,
            body_ar: NotificationMessages?.SHIPMENT_COMPLETED?.BODY?.AR,
          }).save(),
        );
        if (user?.last_login) {
          this.sendFirbaseNotificationService.sendToDevice(
            NotificationMessages?.SHIPMENT_COMPLETED?.TITLE[user[LANG] || EN],
            NotificationMessages?.SHIPMENT_COMPLETED?.BODY[user[LANG] || EN],
            user?.devices,
            { user_id: user?._id?.toString(), shipment_id },
          );
        }
      }
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.SHIPMENT_UPDATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  async verifyShipment(
    shipmentId: string,
    lang: string,
    code: string,
    res: Response,
  ) {
    const shipment = await this.shipmentModel.findById(shipmentId);

    if (!shipment) {
      throw new BadRequestException(ErrorMsg?.INQUIRY_NOT_FOUND[lang || EN]);
    }

    if (shipment.verification_code !== code) {
      throw new BadRequestException('Invalid verification code');
    }

    // Mark as delivered and verified
    shipment.is_verified = true;
    await shipment.save();

    return res.status(HttpStatus.OK).json({
      success: true,
      message: 'Shipment verified',
    });
  }

  /*****************************CREATE SHIPMENT MODE*************************************/
  async createShipmentMode(
    lang: string,
    body: CreateShipmentModeDto,
    res: Response,
  ) {
    try {
      const shipment = await this.shipmentModeModel.findOne(body);
      if (shipment) {
        throw new BadRequestException(ErrorMsg?.MODE_EXIST[lang || EN]);
      }
      await new this.shipmentModeModel(body).save();
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.MODE_CREATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************GET STATISTICS****************************************/
  async getStatistics(
    type: string,
    report: string,
    starting: Date,
    ending: Date,
  ) {
    let label = [];
    const series = [];
    try {
      /////////creating query for finding data//////
      const query = {
        $or: [
          { createdAt: { $gte: starting } },
          { createdAt: { $lte: ending } },
        ],
      };
      if (type) {
        query[CURRENT_STATE] = type;
      }
      ////////creating group query according to report type////////
      let group = {};
      if (report === YEARLY) {
        group = {
          year: { $year: '$createdAt' },
          month: { $month: '$createdAt' },
        };
      } else {
        group = {
          $dateToString: { format: '%Y-%m-%d', date: '$createdAt' },
        };
      }
      const data = await this.shipmentModel.aggregate([
        {
          $match: query,
        },
        {
          $group: {
            _id: group,
            count: { $sum: 1 },
          },
        },
      ]);
      if (report === YEARLY) {
        label = [
          'Jan',
          'Feb',
          'Mar',
          'Apr',
          'May',
          'Jun',
          'Jul',
          'Aug',
          'Sep',
          'Oct',
          'Nov',
          'Dec',
        ];
        for (let i = 1; i < 13; i++) {
          series.push(data.find((item) => item?._id?.month === i)?.count || 0);
        }
      } else if (report === MONTHLY) {
        for (let i = 1; i <= new Date().getUTCDate(); i++) {
          label.push(`${i} ${new Date().toUTCString().split(' ')[2]}`);
          series.push(
            data.find((item) => item?._id?.split('-')[2] == i)?.count || 0,
          );
        }
      } else {
        const today = new Date().getUTCDate();
        const start = new Date(new Date().setUTCDate(today - 7)).getUTCDate();
        for (let i = start; i <= today; i++) {
          label.push(`${i} ${new Date().toUTCString().split(' ')[2]}`);
          series.push(
            data.find((item) => item?._id?.split('-')[2] == i)?.count || 0,
          );
        }
      }
      return { label, series };
    } catch (error) {
      return { label, series };
    }
  }
  /*------------------------------------------------------------------------------------*/

  /********************************DELETE USER*******************************************/
  async deleteUser(body: DeleteUserDto, lang: string, res: Response) {
    try {
      const user = await this.userModel.findOne({ username: body?.username });
      if (!user) {
        throw new BadRequestException(
          ErrorMsg?.USER_NOT_REGISTERED[lang || EN],
        );
      }
      const matchPassword = await bcrypt.compare(
        body?.password,
        user?.password,
      );
      if (!matchPassword) {
        throw new BadRequestException(
          ErrorMsg?.INVALID_CREDENTIALS[lang || EN],
        );
      }
      await this.userModel.findByIdAndUpdate(user?._id, {
        deleted_at: new Date(),
      });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.ACCOUNT_DELETED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*****************************GENERATE SERIAL NUMBER***********************************/
  async generateShipmentSerialNumber() {
    try {
      const shipment = await this.shipmentModel
        .find()
        .sort({ createdAt: -1 })
        .limit(1);
      const serial_number = generateSerialNumber(
        shipment[0]?.serial_number || BASE_SHIPMENT_SERIAL_NO,
      );
      return serial_number;
    } catch (error) {
      return BASE_SHIPMENT_SERIAL_NO;
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*****************************SEND SHIPMENT NOTIFICATION*******************************/
  async sendShipmentNotifications(
    shipment_id: string,
    lang: string,
    type: string,
    res: Response,
  ) {
    try {
      const data = await this.shipmentModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(shipment_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                  is_company: true,
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: {
                    employee_id: '$employee_id',
                    show_invoice: '$show_invoice',
                  },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                        show_invoice: '$$show_invoice',
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
            serial_number: 1,
          },
        },
      ]);
      if (!data[0]) {
        throw new BadRequestException(ErrorMsg?.SHIPMENT_NOT_FOUND[lang || EN]);
      }

      ///////////////User Devices/////////////
      const notificationUsers = [
        data[0]?.company,
        ...data[0]?.company_employees,
      ];

      /////////sending firebase push notifications/////////
      const allPromise = [];
      for (const user of notificationUsers) {
        ///////////////////In App Notifications/////////////
        if (type === NEW_SHIPMENT) {
          allPromise.push(() =>
            this.sendNewShipmentNotification(
              data[0],
              user,
              shipment_id,
              user?.devices,
            ),
          );
        } else if (
          type === SHIPEMENT_INVOICE &&
          (user?.is_company || user?.show_invoice)
        ) {
          allPromise.push(() =>
            this.sendShipmentInvoiceNotification(
              user,
              shipment_id,
              user?.devices,
            ),
          );
        } else if (type === SHIPMENT_DOCUMENT) {
          allPromise.push(() =>
            this.sendShipmentDocumentNotification(
              user,
              shipment_id,
              user?.devices,
            ),
          );
        } else if (type === SHIPEMENT_STATUS) {
          allPromise.push(() =>
            this.sendShipmentStatusNotification(
              user,
              shipment_id,
              user?.devices,
            ),
          );
        }
      }
      const resolved = allPromise.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.USER_NOTIFIED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*****************************SEND INQUIRY NOTIFICATION********************************/
  async sendInquiryNotifications(
    inquiry_id: string,
    lang: string,
    type: string,
    res: Response,
  ) {
    try {
      const data = await this.inquiryModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(inquiry_id),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$user_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'map_user_devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$user',
          },
        },
      ]);
      if (!data[0]) {
        throw new BadRequestException(ErrorMsg?.INQUIRY_NOT_FOUND[lang || EN]);
      }
      const deviceTokens = [];
      if (data[0]?.user?.map_user_devices?.length > 0) {
        for (let i = 0; i < data[0]?.user?.map_user_devices?.length; i++) {
          deviceTokens.push(data[0]?.user?.map_user_devices[i]?.device_token);
        }
      }
      const allPromises = [];
      if (type === REPLY) {
        allPromises.push(() =>
          this.sendReplyInquiryNotification(data[0], inquiry_id, deviceTokens),
        );
      } else if (type === QUOTATION) {
        allPromises.push(() =>
          this.sendQuotationDocumentNotification(
            data[0],
            inquiry_id,
            deviceTokens,
          ),
        );
      }
      const resolved = allPromises.map((item) => item());
      await Promise.allSettled(resolved);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.USER_NOTIFIED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************CREATE USER******************************************/
  async createUser(body: CreateUserDto, lang: string, res: Response) {
    try {
      if (body?.password !== body?.confirm_password) {
        throw new BadRequestException(
          ErrorMsg?.BOTH_PASSWORD_MATCH[lang || EN],
        );
      }
      await new this.userModel({
        ...body,
        password: await bcrypt.hash(body?.password, 10),
      }).save();
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.USER_CREATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************GET USER DETAILS*************************************/
  async getUserDetails(user_id: string, res: Response) {
    try {
      const data = await this.userModel.aggregate([
        {
          $match: { _id: new mongoose.Types.ObjectId(user_id) },
        },
        {
          $lookup: {
            from: 'inquiries',
            as: 'inquiries',
            let: { user_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$user_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_inquiry_attachments',
                  as: 'map_inquiry_attachments',
                  localField: '_id',
                  foreignField: 'inquiry_id',
                },
              },
              {
                $lookup: {
                  from: 'map_inquiry_replies',
                  as: 'map_inquiry_replies',
                  localField: '_id',
                  foreignField: 'inquiry_id',
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'shipments',
            as: 'shipments',
            let: { company_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_shipment_attachments',
                  as: 'map_shipment_attachments',
                  localField: '_id',
                  foreignField: 'shipment_id',
                },
              },
              {
                $lookup: {
                  from: 'map_shipment_commodities',
                  as: 'map_shipment_commodities',
                  localField: '_id',
                  foreignField: 'shipment_id',
                },
              },
              {
                $lookup: {
                  from: 'map_shipment_statuses',
                  as: 'map_shipment_statuses',
                  localField: '_id',
                  foreignField: 'shipment_id',
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_user_devices',
            as: 'map_user_devices',
            let: { user_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$user_id', '$$user_id'],
                  },
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'notifications',
            as: 'notifications',
            let: { user_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$user_id', '$$user_id'],
                  },
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company',
            localField: '_id',
            foreignField: 'company_id',
          },
        },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'employee',
            localField: '_id',
            foreignField: 'employee_id',
          },
        },
        {
          $lookup: {
            from: 'otps',
            as: 'otps',
            let: {
              phone_number: '$phone_number',
              country_phone_code: '$country_phone_code',
            },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $and: [
                      { $eq: ['$phone_number', '$$phone_number'] },
                      { $eq: ['$country_phone_code', '$$country_phone_code'] },
                    ],
                  },
                },
              },
            ],
          },
        },
      ]);
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************HARD DELETE USER*************************************/
  async hardDeleteUser(user_id: string, res: Response) {
    try {
      await this.mapUserDeviceModal.deleteMany({
        user_id: new mongoose.Types.ObjectId(user_id),
      });
      await this.notificationModel.deleteMany({
        user_id: new mongoose.Types.ObjectId(user_id),
      });
      await this.userModel.findByIdAndDelete(user_id);
      const shipments = await this.shipmentModel.find({
        company_id: new mongoose.Types.ObjectId(user_id),
      });
      if (shipments?.length > 0) {
        for (const item of shipments) {
          await this.deleteShipmentAllData(item?._id?.toString());
        }
      }
      const inquiries = await this.inquiryModel.find({
        user_id: new mongoose.Types.ObjectId(user_id),
      });
      if (inquiries?.length > 0) {
        for (const item of inquiries) {
          await this.deleteInquiryAllData(item?._id?.toString());
        }
      }
      await this.mapCompanyEmployeeModel.deleteMany({
        $or: [
          { company_id: new mongoose.Types.ObjectId(user_id) },
          { employee_id: new mongoose.Types.ObjectId(user_id) },
        ],
      });
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 201,
        message: 'Deleted',
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************DELETE SHIPMENT ALL DATA************************************/
  async deleteShipmentAllData(shipment_id: string) {
    try {
      const shipment = await this.shipmentModel.aggregate([
        { $match: { _id: new mongoose.Types.ObjectId(shipment_id) } },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'attachments',
            localField: '_id',
            foreignField: 'shipment_id',
          },
        },
      ]);
      if (shipment[0]) {
        const promiseArr = [];
        promiseArr.push(() =>
          this.shipmentModel.findByIdAndDelete(shipment_id),
        );
        promiseArr.push(() =>
          this.mapShipmentAttachmentModel.deleteMany({
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
          }),
        );
        promiseArr.push(() =>
          this.mapShipmentStatusModel.deleteMany({
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
          }),
        );
        promiseArr.push(() =>
          this.notificationModel.deleteMany({
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
          }),
        );
        promiseArr.push(() =>
          this.mapShipmentCommodityModal.deleteMany({
            shipment_id: new mongoose.Types.ObjectId(shipment_id),
          }),
        );
        const resolved = promiseArr.map((item) => item());
        await Promise.allSettled(resolved);
        ////////////deleting file from local storage if exists/////////
        for (const data of shipment[0]?.attachments) {
          if (fs.existsSync(data?.path)) {
            fs.unlink(data?.path, (err) => {
              if (err) console.log('not found');
              else console.log('deleted');
            });
          } else {
            console.log('not found');
          }
        }
      }
      return true;
    } catch (error) {
      console.log('Not Deleted');
      return false;
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************DELETE INQUIRY ALL DATA*************************************/
  async deleteInquiryAllData(inquiry_id: string) {
    try {
      const inquiry = await this.inquiryModel.aggregate([
        { $match: { _id: new mongoose.Types.ObjectId(inquiry_id) } },
        {
          $lookup: {
            from: 'map_inquiry_attachments',
            as: 'attachments',
            localField: '_id',
            foreignField: 'inquiry_id',
          },
        },
      ]);
      if (inquiry[0]) {
        const promiseArr = [];
        promiseArr.push(() => this.inquiryModel.findByIdAndDelete(inquiry_id));
        promiseArr.push(() =>
          this.mapInquiryAttachmentModel.deleteMany({
            inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
          }),
        );
        promiseArr.push(() =>
          this.mapInquiryReplyModel.deleteMany({
            inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
          }),
        );
        promiseArr.push(() =>
          this.notificationModel.deleteMany({
            inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
          }),
        );
        const resolved = promiseArr.map((item) => item());
        await Promise.allSettled(resolved);
        ////////////deleting file from local storage if exists/////////
        for (const data of inquiry[0]?.attachments) {
          if (fs.existsSync(data?.path)) {
            fs.unlink(data?.path, (err) => {
              if (err) console.log('not found');
              else console.log('deleted');
            });
          } else {
            console.log('not found');
          }
        }
      }
      return true;
    } catch (error) {
      console.log('Not Deleted');
      return false;
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND INQUIRY QUOTATION NOTIFICATIONS************************/
  async sendQuotationDocumentNotification(
    inquiry: any,
    inquiry_id: string,
    device_tokens: any,
  ) {
    await new this.notificationModel({
      user_id: inquiry?.user_id,
      inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
      title_en: NotificationMessages?.QUOTATION_UPLOADED?.TITLE?.EN,
      title_ar: NotificationMessages?.QUOTATION_UPLOADED?.TITLE?.AR,
      body_en: NotificationMessages?.QUOTATION_UPLOADED?.BODY?.EN,
      body_ar: NotificationMessages?.QUOTATION_UPLOADED?.BODY?.AR,
    }).save();
    this.sendFirbaseNotificationService.sendToDevice(
      NotificationMessages?.QUOTATION_UPLOADED?.TITLE[
        inquiry[0]?.user[LANG] || EN
      ],
      NotificationMessages?.QUOTATION_UPLOADED?.BODY[
        inquiry[0]?.user[LANG] || EN
      ],
      device_tokens,
      { user_id: inquiry[0]?.user_id?.toString(), inquiry_id },
    );
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND INQUIRY REPLY NOTIFICATIONS****************************/
  async sendReplyInquiryNotification(
    inquiry: any,
    inquiry_id: string,
    device_tokens: any,
  ) {
    await new this.notificationModel({
      user_id: inquiry?.user_id,
      inquiry_id: new mongoose.Types.ObjectId(inquiry_id),
      title_en: NotificationMessages?.INQUIRY_REPLIED?.TITLE?.EN,
      title_ar: NotificationMessages?.INQUIRY_REPLIED?.TITLE?.AR,
      body_en: NotificationMessages?.INQUIRY_REPLIED?.BODY?.EN,
      body_ar: NotificationMessages?.INQUIRY_REPLIED?.BODY?.AR,
    }).save();
    this.sendFirbaseNotificationService.sendToDevice(
      NotificationMessages?.INQUIRY_REPLIED?.TITLE[inquiry?.user[LANG] || EN],
      NotificationMessages?.INQUIRY_REPLIED?.BODY[inquiry?.user[LANG] || EN],
      device_tokens,
      { user_id: inquiry?.user_id?.toString(), inquiry_id },
    );
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND SHIPMENT DOCUMENT NOTIFICATIONS************************/
  async sendShipmentDocumentNotification(
    user: any,
    shipment_id: string,
    device_tokens: any,
  ) {
    await new this.notificationModel({
      user_id: new mongoose.Types.ObjectId(user?._id),
      shipment_id: new mongoose.Types.ObjectId(shipment_id),
      title_en: NotificationMessages?.NEW_DOCUMENT_UPLOADED?.TITLE?.EN,
      title_ar: NotificationMessages?.NEW_DOCUMENT_UPLOADED?.TITLE?.AR,
      body_en: NotificationMessages?.NEW_DOCUMENT_UPLOADED?.BODY?.EN,
      body_ar: NotificationMessages?.NEW_DOCUMENT_UPLOADED?.BODY?.AR,
    }).save();

    if (user?.last_login) {
      this.sendFirbaseNotificationService.sendToDevice(
        NotificationMessages?.NEW_DOCUMENT_UPLOADED?.TITLE[user[LANG] || EN],
        NotificationMessages?.NEW_DOCUMENT_UPLOADED?.BODY[user[LANG] || EN],
        device_tokens,
        {
          user_id: user?._id?.toString(),
          shipment_id: shipment_id?.toString(),
        },
      );
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND SHIPMENT INVOICE NOTIFICATIONS*************************/
  async sendShipmentInvoiceNotification(
    user: any,
    shipment_id: string,
    device_tokens: any,
  ) {
    await new this.notificationModel({
      user_id: new mongoose.Types.ObjectId(user?._id),
      shipment_id: new mongoose.Types.ObjectId(shipment_id),
      title_en: NotificationMessages?.NEW_INVOICE_UPLOADED?.TITLE?.EN,
      title_ar: NotificationMessages?.NEW_INVOICE_UPLOADED?.TITLE?.AR,
      body_en: NotificationMessages?.NEW_INVOICE_UPLOADED?.BODY?.EN,
      body_ar: NotificationMessages?.NEW_INVOICE_UPLOADED?.BODY?.AR,
    }).save();
    if (user?.last_login) {
      this.sendFirbaseNotificationService.sendToDevice(
        NotificationMessages?.NEW_INVOICE_UPLOADED?.TITLE[user[LANG] || EN],
        NotificationMessages?.NEW_INVOICE_UPLOADED?.BODY[user[LANG] || EN],
        device_tokens,
        {
          user_id: user?._id?.toString(),
          shipment_id: shipment_id?.toString(),
        },
      );
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND SHIPMENT RECEVEING SLIP NOTIFICATIONS*************************/
  async sendReceivingSlipNotification(
    user: any,
    shipment_id: string,
    device_tokens: any,
  ) {
    await new this.notificationModel({
      user_id: new mongoose.Types.ObjectId(user?._id),
      shipment_id: new mongoose.Types.ObjectId(shipment_id),
      title_en: NotificationMessages?.NEW_RECEIV_SLIP?.TITLE?.EN,
      title_ar: NotificationMessages?.NEW_RECEIV_SLIP?.TITLE?.AR,
      body_en: NotificationMessages?.NEW_RECEIV_SLIP?.BODY?.EN,
      body_ar: NotificationMessages?.NEW_RECEIV_SLIP?.BODY?.AR,
    }).save();
    if (user?.last_login) {
      this.sendFirbaseNotificationService.sendToDevice(
        NotificationMessages?.NEW_RECEIV_SLIP?.TITLE[user[LANG] || EN],
        NotificationMessages?.NEW_RECEIV_SLIP?.BODY[user[LANG] || EN],
        device_tokens,
        {
          user_id: user?._id?.toString(),
          shipment_id: shipment_id?.toString(),
        },
      );
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND SHIPMENT STATUS NOTIFICATIONS**************************/
  async sendShipmentStatusNotification(
    user: any,
    shipment_id: string,
    device_tokens: any,
  ) {
    try {
      await new this.notificationModel({
        user_id: new mongoose.Types.ObjectId(user?._id),
        shipment_id: new mongoose.Types.ObjectId(shipment_id),
        title_en: NotificationMessages?.NEW_STATUS_ADDED?.TITLE?.EN,
        title_ar: NotificationMessages?.NEW_STATUS_ADDED?.TITLE?.AR,
        body_en: NotificationMessages?.NEW_STATUS_ADDED?.BODY?.EN,
        body_ar: NotificationMessages?.NEW_STATUS_ADDED?.BODY?.AR,
      }).save();
      if (user?.last_login) {
        this.sendFirbaseNotificationService.sendToDevice(
          NotificationMessages?.NEW_STATUS_ADDED?.TITLE[user[LANG] || EN],
          NotificationMessages?.NEW_STATUS_ADDED?.BODY[user[LANG] || EN],
          device_tokens,
          {
            user_id: user?._id?.toString(),
            shipment_id: shipment_id?.toString(),
          },
        );
      }
    } catch (error) {
      console.log(error);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /**************************SEND NEW SHIPMENT NOTIFICATIONS*****************************/
  async sendNewShipmentNotification(
    shipment: any,
    user: any,
    shipment_id: string,
    device_tokens: any,
  ) {
    try {
      const notificationData = await notificationHelper(
        capitalizeFull(user.first_name) + ' ' + capitalizeFull(user?.last_name),
        shipment?.serial_number,
        new Date(),
      );
      ////////////saving notification/////////
      await new this.notificationModel({
        user_id: new mongoose.Types.ObjectId(user?._id),
        shipment_id: new mongoose.Types.ObjectId(shipment_id),
        title_en: notificationData?.title?.EN,
        title_ar: notificationData?.title?.AR,
        body_en: notificationData?.body?.EN,
        body_ar: notificationData?.body?.AR,
      }).save();
      if (user?.last_login) {
        ////////////sending firebase notification/////////
        this.sendFirbaseNotificationService.sendToDevice(
          notificationData?.title[user[LANG] || EN],
          notificationData?.body[user[LANG] || EN],
          device_tokens,
          {
            user_id: user?._id?.toString(),
            shipment_id: shipment_id?.toString(),
          },
        );
      }
    } catch (error) {
      console.log(error);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************UPDATE SINGLE USER***********************************/
  async updateSingleUser(
    user_id: string,
    body: UpdateSingleUserDto,
    res: Response,
  ) {
    try {
      const obj = { ...body };
      if (body?.delete) {
        obj[DELETED_AT] = null;
      }
      if (body?.verify) {
        obj[PHONE_NUMBER_VERIFIED_AT] = new Date();
        obj[LAST_LOGIN] = new Date();
      }
      await this.userModel.findByIdAndUpdate(user_id, obj);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        message: 'Updated successfully',
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************GET DUMMY USERS**************************************/
  async getDummyUsers(page = 1, limit = 10, res: Response) {
    try {
      const data = await this.userModel
        .find({ last_login: null })
        .skip(Number(page - 1) * Number(limit))
        .limit(Number(limit));
      const total = await this.userModel.countDocuments({ last_login: null });
      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        current_page: Number(page),
        total_pages: Math.ceil(total / Number(limit)) || 0,
        limit: Number(limit),
        total: Number(total),
        data,
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************ASSIGN ADMIN*****************************************/
  async assignAdmin(user_id: string, lang: string, res: Response) {
    try {
      const user = await this.userModel.findById(user_id);
      if (!user) {
        throw new BadRequestException(ErrorMsg?.USER_NOT_FOUND[lang || EN]);
      }
      await this.userModel.findByIdAndUpdate(user_id, {
        is_admin: !user?.is_admin,
      });

      return res.status(201).json({
        success: true,
        statusCode: 201,
        message: user?.is_admin
          ? SuccessMsg?.ADMIN_REMOVED[lang || EN]
          : SuccessMsg?.ADMIN_ASSIGNED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  //   async assignRole( res: Response , user_id: string, role:AssignRoleDto ,  lang: string) {
  //   try {
  //     console.log(role , "role");
  //     const user = await this.userModel.findById(user_id);
  //     if (!user) {
  //       throw new BadRequestException(ErrorMsg?.USER_NOT_FOUND[lang || EN]);
  //     }
  //     console.log(user , "user")
  //     // Prevent assigning warehouse admin if already admin
  //     if (role === 'WAREHOUSEEMPLOYEE' && user.is_admin) {
  //       throw new BadRequestException('User is already an admin, cannot assign warehouse admin');
  //     }

  //     // Prevent assigning admin if already warehouse admin
  //     if (role === 'ADMIN' && user.is_warehouse_admin) {
  //       throw new BadRequestException('User is already a warehouse admin, cannot assign admin');
  //     }

  //     let update: any = {};
  //     let message: string;

  //     if (role === 'ADMIN') {
  //       update.is_admin = !user.is_admin;
  //       message = user.is_admin
  //         ? SuccessMsg?.ADMIN_REMOVED[lang || EN]
  //         : SuccessMsg?.ADMIN_ASSIGNED[lang || EN];
  //     } else if (role === 'WAREHOUSEEMPLOYEE') {
  //       update.is_warehouse_admin = !user.is_warehouse_admin;
  //       message = user.is_warehouse_admin
  //         ? SuccessMsg?.WAREHOUSE_EMPLOYEE_REMOVED[lang || EN]
  //         : SuccessMsg?.WAREHOUSE_EMPLOYEE_ASSIGNED[lang || EN];
  //     }
  // console.log(update , message , "update and message")
  //     await this.userModel.findByIdAndUpdate(user_id, update);

  //     return res.status(201).json({
  //       success: true,
  //       statusCode: 201,
  //       message,
  //     });
  //   } catch (error) {
  //     throw new CustomException(error, error.status);
  //   }
  // }

  /*------------------------------------------------------------------------------------*/

  /*************************************GET PROFILE**************************************/
  async getProfile(req: Request, res: Response) {
    try {
      return res.status(200).json({
        success: true,
        statusCode: 200,
        data: req[ADMIN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /******************************UNDO COMPLETE SHIPMENT**********************************/
  async undoCompleteShipment(shipment_id: string, res: Response) {
    try {
      await this.shipmentModel.findByIdAndUpdate(shipment_id, {
        current_state: ACTIVE,
      });
      return res.status(201).json({
        success: true,
        statusCode: 201,
        message: 'Done',
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************DELETE DEVICE****************************************/
  async deleteDevices(single_device_id: string, res: Response) {
    try {
      await this.mapUserDeviceModal.findByIdAndDelete(single_device_id);
      return res.status(200).json({
        success: true,
        statusCode: 200,
        message: 'Done',
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*********************************DELETE DEVICE****************************************/
  async searchModules(page = 1, limit = 10, search: string, res: Response) {
    try {
      const usersData = await this.userModel.aggregate([
        {
          $addFields: {
            full_name: { $concat: ['$first_name', ' ', '$last_name'] },
          },
        },
        {
          $match: {
            $or: [
              { full_name: { $regex: `.*${search}.*`, $options: 'i' } },
              { phone_number: { $regex: `.*${search}.*`, $options: 'i' } },
              { username: { $regex: `.*${search}.*`, $options: 'i' } },
            ],
            last_login: { $ne: null }, ///////checking if is login or not////////
          },
        },
        {
          $skip: (Number(page) - 1) * Number(limit),
        },
        { $limit: Number(limit) },
        {
          $project: { data: search, module: 'in users' },
        },
        {
          $facet: {
            paginatedResults: [
              { $skip: (Number(page) - 1) * Number(limit) },
              { $limit: Number(limit) },
            ],
            totalCount: [{ $count: 'count' }],
          },
        },
        {
          $addFields: {
            total: {
              $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
            },
          },
        },
        {
          $project: {
            paginatedResults: 1,
            total: 1,
          },
        },
      ]);
      const shipmentData = await this.shipmentModel.aggregate([
        {
          $lookup: {
            from: 'users',
            as: 'user',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$user',
          },
        },
        {
          $lookup: {
            from: 'shipment_modes',
            as: 'shipment_mode',
            let: { mode_id: '$shipment_mode' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$mode_id'],
                  },
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: '$shipment_mode',
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $lookup: {
            from: 'map_shipment_statuses',
            as: 'shipment_status',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$shipment_id', '$$shipment_id'],
                  },
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'shipment_attachments',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$shipment_id', '$$shipment_id'],
                  },
                  name: 'shipment_document',
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_attachments',
            as: 'shipment_invoice',
            let: { shipment_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$shipment_id', '$$shipment_id'],
                  },
                  name: 'shipment_invoice',
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
              {
                $project: {
                  image: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_shipment_commodities',
            as: 'commodity',
            localField: '_id',
            foreignField: 'shipment_id',
          },
        },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'company_employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: {
                  path: '$company_employee',
                },
              },
              {
                $project: {
                  first_name: '$company_employee.first_name',
                  last_name: '$company_employee.last_name',
                  phone_number: '$company_employee.phone_number',
                  country_phone_code: '$company_employee.country_phone_code',
                  _id: 0,
                  employee_id: '$company_employee._id',
                  show_invoice: 1,
                },
              },
            ],
          },
        },
        {
          $match: {
            $or: [
              { pickup_from_en: { $regex: `.*${search}.*`, $options: 'i' } },
              { pickup_from_ar: { $regex: `.*${search}.*`, $options: 'i' } },
              { delivered_to_en: { $regex: `.*${search}.*`, $options: 'i' } },
              { delivered_to_ar: { $regex: `.*${search}.*`, $options: 'i' } },
              { person_name_agent: { $regex: `.*${search}.*`, $options: 'i' } },
              { bill_of_lading: { $regex: `.*${search}.*`, $options: 'i' } },
              { vessel_name: { $regex: `.*${search}.*`, $options: 'i' } },
              { voyage: { $regex: `.*${search}.*`, $options: 'i' } },
              { agent: { $regex: `.*${search}.*`, $options: 'i' } },
              {
                'shipment_mode.name_en': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'shipment_mode.name_ar': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'shipment_mode.slug': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              { bill_of_lading: { $regex: `.*${search}.*`, $options: 'i' } },
              { serial_number: { $regex: `.*${search}.*`, $options: 'i' } },
              {
                'user.first_name': { $regex: `.*${search}.*`, $options: 'i' },
              },
              {
                'user.last_name': { $regex: `.*${search}.*`, $options: 'i' },
              },
              { 'user.username': { $regex: `.*${search}.*`, $options: 'i' } },
              {
                'user.phone_number': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'user.company_name': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'shipment_status.status_en': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'shipment_status.status_ar': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'commodity.name_en': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'commodity.name_ar': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'commodity.volume': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'commodity.weight': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'commodity.quantity': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'employees.first_name': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'employees.last_name': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'employees.phone_number': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'shipment_invoice.original_name': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'shipment_attachments.original_name': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
            ],
          },
        },
        {
          $skip: (Number(page) - 1) * Number(limit),
        },
        { $limit: Number(limit) },
        {
          $project: {
            data: search,
            module: 'in shipments',
          },
        },
        {
          $facet: {
            paginatedResults: [
              { $skip: (Number(page) - 1) * Number(limit) },
              { $limit: Number(limit) },
            ],
            totalCount: [{ $count: 'count' }],
          },
        },
        {
          $addFields: {
            total: {
              $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
            },
          },
        },
        {
          $project: {
            paginatedResults: 1,
            total: 1,
          },
        },
      ]);
      const inquiryData = await this.inquiryModel.aggregate([
        {
          $lookup: {
            from: 'map_inquiry_attachments',
            as: 'quotations',
            let: { inquiry_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$inquiry_id', '$$inquiry_id'],
                  },
                },
              },
              {
                $project: {
                  document: { $concat: [process.env.BASE_URL, '$path'] },
                  uploaded_by: 1,
                  createdAt: 1,
                  original_name: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: 'map_inquiry_replies',
            as: 'replies',
            let: { inquiry_id: '$_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$inquiry_id', '$$inquiry_id'],
                  },
                },
              },
              {
                $sort: {
                  createdAt: -1,
                },
              },
            ],
          },
        },
        {
          $match: {
            $or: [
              {
                name: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                email: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                phone_number: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                inquiry: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                equipments: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                commodity: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                request: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                pickup: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                delivery: {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'quotations.original_name': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
              {
                'replies.message': {
                  $regex: `.*${search}.*`,
                  $options: 'i',
                },
              },
            ],
          },
        },
        {
          $skip: (Number(page) - 1) * Number(limit),
        },
        { $limit: Number(limit) },
        {
          $project: { data: search, module: 'in inquiries' },
        },
        {
          $facet: {
            paginatedResults: [
              { $skip: (Number(page) - 1) * Number(limit) },
              { $limit: Number(limit) },
            ],
            totalCount: [{ $count: 'count' }],
          },
        },
        {
          $addFields: {
            total: {
              $ifNull: [{ $arrayElemAt: ['$totalCount.count', 0] }, 0],
            },
          },
        },
        {
          $project: {
            paginatedResults: 1,
            total: 1,
          },
        },
      ]);
      const modes = await this.shipmentModeModel
        .find({
          $or: [
            { name_en: { $regex: `.*${search}.*`, $options: 'i' } },
            { slug: { $regex: `.*${search}.*`, $options: 'i' } },
            { name_ar: { $regex: `.*${search}.*`, $options: 'i' } },
          ],
        })
        .skip((Number(page) - 1) * Number(limit))
        .limit(Number(limit));
      const modesCount = await this.shipmentModeModel.countDocuments({
        $or: [
          { name_en: { $regex: `.*${search}.*`, $options: 'i' } },
          { slug: { $regex: `.*${search}.*`, $options: 'i' } },
          { name_ar: { $regex: `.*${search}.*`, $options: 'i' } },
        ],
      });
      const modesData = modes.map((item) => {
        return { _id: item?._id, data: search, module: 'in modes' };
      });
      const data = [
        ...usersData[0].paginatedResults,
        ...shipmentData[0].paginatedResults,
        ...inquiryData[0].paginatedResults,
        ...modesData,
      ];

      const total =
        Number(usersData[0].total) +
        Number(shipmentData[0].total) +
        Number(inquiryData[0].total) +
        modesCount;

      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        current_page: search ? Number(page) : 1,
        total_pages: search ? Math.ceil(total / Number(40)) || 0 : 0,
        total: search ? total : 0,
        data: search ? data : [],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /*****************************GET SINGLE USER DATA*************************************/
  async getSingleUserData(user_id: string, res: Response) {
    try {
      const data = await this.userModel.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(user_id),
          },
        },
        {
          $addFields: {
            full_name: { $concat: ['$first_name', ' ', '$last_name'] },
          },
        },
        {
          $project: {
            full_name: 1,
            username: 1,
            phone_number: 1,
            country_phone_code: 1,
            city: 1,
            country: 1,
            createdAt: 1,
            is_blocked: 1,
            phone_number_verified_at: 1,
            is_admin: 1,
            first_name: 1,
            last_name: 1,
            last_login: 1,
          },
        },
      ]);

      // @@start this is for count of all shiments
      const companyId = new Types.ObjectId(user_id);

      const baseQuery: any = {
        company_id: companyId,
      };

      // Total Shipments
      const total = await this.shipmentModel.countDocuments(baseQuery);
      // Active Shipments
      const active = await this.shipmentModel.countDocuments({
        ...baseQuery,
        [CURRENT_STATE]: ACTIVE,
      });

      // Past / Completed Shipments
      const completed = await this.shipmentModel.countDocuments({
        ...baseQuery,
        [CURRENT_STATE]: COMPLETED,
      });
      // @@end this is for count of all shiments

      data[0].shipment_counts = {
        total,
        active,
        completed,
      };

      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data: data[0] || {},
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************SEND NOTIFICATIONS TO ALL USERS*******************************/
  async sendNotificationToAllUsers(lang: string, res: Response) {
    try {
      const data = await this.shipmentModel.aggregate([
        {
          $match: {
            current_state: ACTIVE,
            // _id: new mongoose.Types.ObjectId('683e84d18d0bbf5ca2bd4dd5'),
          },
        },
        {
          $lookup: {
            from: 'users',
            as: 'company',
            let: { user_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$_id', '$$user_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'map_user_devices',
                  as: 'devices',
                  localField: '_id',
                  foreignField: 'user_id',
                },
              },
              {
                $project: {
                  first_name: 1,
                  last_name: 1,
                  last_login: 1,
                  lang: 1,
                  devices: {
                    $map: {
                      input: '$devices',
                      as: 'device',
                      in: '$$device.device_token',
                    },
                  },
                },
              },
            ],
          },
        },
        { $unwind: { path: '$company' } },
        {
          $lookup: {
            from: 'map_company_employees',
            as: 'company_employees',
            let: { company_id: '$company_id' },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $eq: ['$company_id', '$$company_id'],
                  },
                },
              },
              {
                $lookup: {
                  from: 'users',
                  as: 'employee',
                  let: { employee_id: '$employee_id' },
                  pipeline: [
                    {
                      $match: {
                        $expr: {
                          $eq: ['$_id', '$$employee_id'],
                        },
                      },
                    },
                    {
                      $lookup: {
                        from: 'map_user_devices',
                        as: 'devices',
                        localField: '_id',
                        foreignField: 'user_id',
                      },
                    },
                    {
                      $project: {
                        first_name: 1,
                        last_name: 1,
                        last_login: 1,
                        lang: 1,
                        devices: {
                          $map: {
                            input: '$devices',
                            as: 'device',
                            in: '$$device.device_token',
                          },
                        },
                      },
                    },
                  ],
                },
              },
              {
                $unwind: { path: '$employee' },
              },
            ],
          },
        },
        {
          $project: {
            company: 1,
            company_id: 1,
            company_employees: '$company_employees.employee',
          },
        },
      ]);
      const users = [];
      const device_tokens = [];
      const allPromises = [];
      for (const item of data) {
        const findUser = users.find(
          (user) => user?.user_id === item?.company_id?.toString(),
        );
        if (!findUser) {
          users.push({
            shipment_id: item._id?.toString(),
            user_id: item?.company_id?.toString(),
          });
          // device_tokens.push(...item?.company?.devices);
          allPromises.push(() =>
            this.sendAndSaveNotificationToAllUsers(
              item._id?.toString(),
              item?.company_id?.toString(),
              item?.company?.devices,
              item?.company?.lang,
            ),
          );
        }
        for (const employee of item?.company_employees) {
          const findUser = users.find(
            (obj) => obj?.user_id === employee?._id?.toString(),
          );
          if (!findUser) {
            users.push({
              shipment_id: item._id?.toString(),
              user_id: employee?._id?.toString(),
            });
            // device_tokens.push(...employee?.devices);
            allPromises.push(() =>
              this.sendAndSaveNotificationToAllUsers(
                item._id?.toString(),
                employee?._id?.toString(),
                employee?.devices,
                employee?.lang,
              ),
            );
          }
        }
      }
      setTimeout(() => {
        const promises = allPromises?.map((item) => item());
        Promise.allSettled(promises);
      }, 0);
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.PROCESS_INITIATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
  /*------------------------------------------------------------------------------------*/

  /************************SEND NOTIFICATIONS TO ALL USERS*******************************/
  async sendAndSaveNotificationToAllUsers(
    shipment_id: string,
    user_id: string,
    device_tokens: any,
    lang: string,
  ) {
    try {
      await new this.notificationModel({
        user_id: new mongoose.Types.ObjectId(user_id),
        shipment_id: new mongoose.Types.ObjectId(shipment_id),
        title_en: NotificationMessages?.NEW_NOTIFICATION?.TITLE?.EN,
        title_ar: NotificationMessages?.NEW_NOTIFICATION?.TITLE?.AR,
        body_en: NotificationMessages?.NEW_NOTIFICATION?.BODY?.EN,
        body_ar: NotificationMessages?.NEW_NOTIFICATION?.BODY?.AR,
      }).save();
      this.sendFirbaseNotificationService.sendToDevice(
        NotificationMessages?.NEW_NOTIFICATION?.TITLE[lang || EN],
        NotificationMessages?.NEW_NOTIFICATION?.BODY[lang || EN],
        device_tokens,
        {
          user_id: user_id?.toString(),
          shipment_id: shipment_id?.toString(),
        },
      );
    } catch (error) {
      console.log(error);
    }
  }
  /*------------------------------------------------------------------------------------*/

  // @@start this is register function for admin to register user
  async Register(lang: string, body: UserRegisterDto, res: Response) {
    try {
      const findUser = await this.userModel.findOne({
        $or: [
          { username: body?.username },
          {
            phone_number: body?.phone_number,
            country_phone_code: body?.country_phone_code,
          },
        ],
        deleted_at: null,
      });
      if (findUser && findUser?.last_login !== null) {
        throw new BadRequestException(
          ErrorMsg?.USER_ALREADY_REGISTERED[lang || EN],
        );
      }
      if (findUser && findUser.created_by == 'admin') {
        throw new BadRequestException(
          ErrorMsg?.USER_ALREADY_REGISTERED[lang || EN],
        );
      }

      //password generate
      const currentYear = new Date().getFullYear().toString();
      const usernamePart =
        body.username && body.username.length >= 4
          ? body.username.substring(0, 4)
          : '0000';
      const password = `${usernamePart}${currentYear}`;

      const hashedPassword = await bcrypt.hash(password, 10);

      if (findUser) {
        await this.userModel.findByIdAndUpdate(
          findUser._id,
          {
            first_name: body?.first_name,
            last_name: body?.last_name,
            username: body?.username,
            password: hashedPassword,
            country_phone_code: body?.country_phone_code,
          },
          { new: true },
        );
      } else {
        await new this.userModel({
          first_name: body?.first_name,
          last_name: body?.last_name,
          username: body?.username,
          password: hashedPassword,
          country_phone_code: body?.country_phone_code,
          phone_number: body?.phone_number,
          phone_number_verified_at: new Date(),
          last_login: new Date(),
          created_by: 'admin',
        }).save();
      }

      await this.sendMsg91PasswordService.sendMsg91Password(
        body?.country_phone_code,
        modifyOtpNumber(body?.phone_number),
        password,
        body?.username || body?.first_name,
      );
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        message: SuccessMsg?.USER_REGISTERED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  async getUserShipmentCounts(userId: string, res: Response) {
    try {
      const companyId = new Types.ObjectId(userId);

      // Base filter (user-wise)
      const baseQuery: any = {
        company_id: companyId,
      };

      // Total Shipments
      const total = await this.shipmentModel.countDocuments(baseQuery);

      // Active Shipments
      const active = await this.shipmentModel.countDocuments({
        ...baseQuery,
        [CURRENT_STATE]: ACTIVE,
      });

      // Past / Completed Shipments
      const completed = await this.shipmentModel.countDocuments({
        ...baseQuery,
        [CURRENT_STATE]: COMPLETED,
      });

      return res.status(HttpStatus.OK).json({
        success: true,
        statusCode: 200,
        data: {
          total,
          active,
          completed,
        },
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  // ################################# QUOTATION #######################

  async createQuotation(lang: string, body: CreateQuotationDto, res: Response) {
    try {
      const quotation = await this.quotationModal.create({ ...body });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        data: quotation,
        message: SuccessMsg?.QUOTATION_CREATED[lang || EN],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  async updateQuotation(
    lang: string,
    body: CreateQuotationDto,
    res: Response,
    id: string,
  ) {
    try {
      const updateQuotation = await this.quotationModal.findByIdAndUpdate(
        id,
        { ...body },
        { new: true },
      );
      if (updateQuotation) {
        return res.status(HttpStatus.OK).json({
          success: true,
          statusCode: 200,
          data: updateQuotation,
          message: SuccessMsg?.QUOTATION_UPDATED[lang || EN],
        });
      } else {
        return res.status(HttpStatus.NOT_FOUND).json({
          success: false,
          statusCode: 404,
          message: ErrorMsg?.QUOTATION_NOT_FOUND[lang || EN],
        });
      }
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  async deleteQuotation(lang: string, res: Response, id: string) {
    try {
      const deleteQuotation = await this.quotationModal.findByIdAndDelete(id);
      if (deleteQuotation) {
        return res.status(HttpStatus.OK).json({
          success: true,
          statusCode: 200,
          message: SuccessMsg?.QUOTATION_DELETE[lang || EN],
        });
      } else {
        return res.status(HttpStatus.NOT_FOUND).json({
          success: false,
          statusCode: 404,
          message: ErrorMsg?.QUOTATION_NOT_FOUND[lang || EN],
        });
      }
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  async getQuotation(lang: string, res: Response, id: string) {
    try {
      const quotations = await this.quotationModal.aggregate([
        {
          $match: {
            _id: new mongoose.Types.ObjectId(id), 
          },
        },
        {
          $lookup: {
            from: 'estimates',
            localField: '_id',
            foreignField: 'quotation_id',
            as: 'estimate',
          },
        },
        {
          $unwind: {
            path: '$estimate',
            preserveNullAndEmptyArrays: true,
          },
        },
      ]);
      return res.status(HttpStatus.OK).json({
        success: true,
        data: quotations[0]
      });
    } catch (error:any) {
      throw new CustomException(error, error.status);
    }
  }

  async getAllQuotation(
    lang: string,
    res: Response,
    page: number,
    limit: number,
    search: string,
    status: string,
  ) {
    try {
      page = page || 1;
      limit = limit || 10;
      const skip = Math.floor((page - 1) * limit);
      const filter: any = {};
      const statusArr = ['lost', 'confirm',"active"];
      if (search) {
        filter.$or = [
          { id: { $regex: search, $options: 'i' } },
          { name: { $regex: search, $options: 'i' } },
          { commodity: { $regex: search, $options: 'i' } },
          { equipment: { $regex: search, $options: 'i' } },
          { from: { $regex: search, $options: 'i' } },
          { to: { $regex: search, $options: 'i' } },
        ];
      }
      if (statusArr.includes(status)) {
        filter.status = status;
      }
     if (status === 'idle') {
  filter.status = { $in: ['idle', '',null] };
}

      const quotations = await this.quotationModal.aggregate([
        {
          $match: filter,
        },
        {
          $lookup: {
            from: 'estimates',
            localField: '_id',
            foreignField: 'quotation_id',
            as: 'estimate',
          },
        },
        {
          $unwind: { path: '$estimate', preserveNullAndEmptyArrays: true },
        },
        {
          $sort: { createdAt: -1 },
        },
        {
          $skip: skip,
        },
        {
          $limit: limit,
        },
      ]);
      //  const quotations = await this.quotationModal
      // .find(filter)
      // .skip(skip)
      // .limit(limit)
      // .sort({ createdAt: -1 });
      const quotationCounts = await this.quotationModal.aggregate([
        {
          $group: {
            _id: null,
            idleCount: {
  $sum: {
    $cond: [
      {
        $in: ['$status', ['idle', '', null]],
      },
      1,
      0,
    ],
  },
},
            activeCount: {
              $sum: { $cond: [{ $eq: ['$status', 'active'] }, 1, 0] },
            },
            lostCount: {
              $sum: { $cond: [{ $eq: ['$status', 'lost'] }, 1, 0] },
            },
            confirmCount: {
              $sum: { $cond: [{ $eq: ['$status', 'confirm'] }, 1, 0] },
            },
            total: { $sum: 1 },
          },
        },
        {
          $project: { _id: 0 },
        },
      ]);
      const total_pages = Math.ceil(
        (await this.quotationModal.countDocuments(filter)) / 10,
      );
      return res.status(HttpStatus.OK).json({
        success: true,
        current_page: page,
        limit,
        total_pages: total_pages,
        data: quotations,
        ...quotationCounts[0],
      });
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }

  // ############################## GENRATE ESTIMATE #############################

  async createEstimate(lang: string, body: CreateEstimateDto, res: Response) {
    try {
      const exists = await this.estimateModal.findOne({
        quotation_id: body.quotation_id,
      });
      if (exists)
        return res.status(HttpStatus.BAD_REQUEST).json({
          success: true,
          statusCode: 201,
          data: exists,
          message: SuccessMsg?.ESTIMATE_EXISTS[lang || EN],
        });
      const quotation = await this.estimateModal.create({ ...body });
      return res.status(HttpStatus.CREATED).json({
        success: true,
        statusCode: 201,
        data: quotation,
        message: SuccessMsg?.ESTIMATE_CREATED[lang || EN],
      });
    } catch (error: any) {
      throw new CustomException(error, error.status);
    }
  }

  async updateEstimate(
    lang: string,
    body: CreateEstimateDto,
    res: Response,
    id: string,
  ) {
    try {
      const updateEstimate = await this.estimateModal.findByIdAndUpdate(
        id,
        { ...body },
        { new: true },
      );
      if (updateEstimate) {
        return res.status(HttpStatus.OK).json({
          success: true,
          statusCode: 200,
          data: updateEstimate,
          message: SuccessMsg?.QUOTATION_UPDATED[lang || EN],
        });
      } else {
        return res.status(HttpStatus.NOT_FOUND).json({
          success: false,
          statusCode: 404,
          message: ErrorMsg?.QUOTATION_NOT_FOUND[lang || EN],
        });
      }
    } catch (error) {
      throw new CustomException(error, error.status);
    }
  }
}
