import { Injectable, HttpException, HttpStatus, Res } from "@nestjs/common"
import { InjectRepository } from "@nestjs/typeorm"
import { Repository, Like, Not, In, Raw, LessThan, LessThanOrEqual, IsNull } from "typeorm"
import { classToPlain } from "class-transformer"
import { responseMessages } from "../../messages/response-messages"
import { emailMessages } from "../../messages/email-messages"
import { InfluencerRegisterRepository } from "./influencer-register.repository"
import * as bcrypt from "bcryptjs"
import axios from 'axios';
import { Constants } from "../../common/constants"
import { JwtService } from "@nestjs/jwt"
const moment = require("moment-timezone")
import { SendMailService } from "../../common/config/send-mail.service"

// Entities Files
import { UserRoles, Users } from "../../entities/users.entity"
import { BrandIndustries } from "../../entities/brand-industries.entity"
import { Settings } from "../../entities/settings.entity"
import slugify from 'slugify';
const { slugify: translitSlug } = require("transliteration");

// DTO Files
import { SocialMediasDto } from "./dtos/social-media.dto"
import { SecondStepDto } from "./dtos/second-step.dto"
import { ThirdStepDto } from "./dtos/third-step.dto"
import { YoutubeServices } from "src/common/services/youtube/youtube.service"
import { SocialMedias } from "src/entities/social-medias.entity"
import { FacebookServices } from "src/common/services/facebook/facebook.service"
import { InstagramServices } from "src/common/services/instagram/instagram.service"
import { TiktokServices } from "src/common/services/tiktok/tiktok.service"
import { UnlinkAccountQueryDto } from "./dtos/unlink-account-query.dto"
import { UnlinkAccountBodyDto } from "./dtos/unlink-account-body.dto"
import { InfluencerSlugParamDto } from "./dtos/influencer-slug-param.dto"
import { InfluencerUpdateDto } from "./dtos/influencer-update.dto"
import { InfluencerKeywords } from "./dtos/influencer-keywords.dto"
import { SocialMediasEditDto } from "./dtos/social-media-edit.dto"
import { XiaohongshuModule } from "src/common/services/xiaohongshu/xiaohongshu.module"
import { XiaohongshuServices } from "src/common/services/xiaohongshu/xiaohongshu.service"
import { SocialMediasLivePostDto } from "./dtos/social-media-live-posts.dto"
import { BankAccountDto } from "./dtos/bank-account.dto"
import { BankDetails } from "src/entities/bank-details.entity"
import { BankIdDto } from "./dtos/bank-id-param.dto"
import { UsersServices } from "src/common/services/users/users.service"
import { EncryptionService } from "src/common/services/encryption/encryption.service"
import { ErrorLogService } from "src/common/services/error-logs/error-log.service"
import { ApifyServices } from "src/common/services/apify/apify.service"
import { CommonService } from "../common/common.services"
import { Campaign, CampaignStatus } from "src/entities/campaign.entity"
import { Posts } from "src/entities/posts.entity"
import { WhatsAppServices } from "src/common/services/whatsapp/whatsapp.service"
import { notificationSettings } from "src/messages/notification-settings"
import { CampaignRepository } from "../campaign/campaign.repository"

@Injectable()
export class InfluencerRegisterService {
    constructor(
        private youtubeServices: YoutubeServices,
        private facebookServices: FacebookServices,
        private instagramServices: InstagramServices,
        private sendMailService: SendMailService,
        private tiktokService: TiktokServices,
        private influencerRegisterRepository: InfluencerRegisterRepository,
        private xiaohongshuService: XiaohongshuServices,
        private jwtService: JwtService,
        private userServices: UsersServices,
        private readonly encryptService: EncryptionService,
        private readonly errorLogService: ErrorLogService,
        private readonly apifyService: ApifyServices,
        private commonService: CommonService,
        private whatsappServices: WhatsAppServices,
        private campaignRepository: CampaignRepository,
        @InjectRepository(Users)
        private Users: Repository<Users>,

        @InjectRepository(SocialMedias)
        private SocialMedias: Repository<SocialMedias>,

        @InjectRepository(Settings)
        private Settings: Repository<Settings>,

        @InjectRepository(BankDetails)
        private BankDetails: Repository<BankDetails>,

        @InjectRepository(Campaign)
        private Campaign: Repository<Campaign>,

        @InjectRepository(Posts)
        private Posts: Repository<Posts>,
    ) { }

    /**
     * Adds a new social media account to the user's profile.
     *
     * @param request - An instance of SocialMediasDto containing the social media account's id and type.
     * @param authUser - The authenticated user object performing the link action.
     *
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @throws HttpException - Throws a 400 error if the social media account already exists.
     * @throws HttpException - Throws a 400 error if the social media type is invalid.
     *
     * After linking, the user's total followers and following counts are increased accordingly.
     */
    async socialMedia(request: SocialMediasDto, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        const socialMediaExists = await this.SocialMedias.findOne({
            where: {
                users: { id: Not(authUser.id), deleted_at: IsNull() },
                social_user_name: Raw(alias => `LOWER(${alias}) = LOWER(:username)`, { username: request.social_user_name }),
                social_type: request.social_media_type,
                is_verified: true
            }
        });
        if (socialMediaExists) {
            throw new HttpException(responseMessages[lang].user.social_media.arealy_exists, HttpStatus.RESET_CONTENT)
        }

        // CHECK IF UNVERIFIED SOCIAL MEDIA EXISTS & LINK WITH VERIFIED SOCIAL MEDIA ACCOUNT THEN WE SWITCH USER
        // const unlinkUnverifiedSocialMedia = await this.SocialMedias.findOne({ relations: ['users'], where: { social_user_name: request.social_user_name, social_type: request.social_media_type, is_verified: false } })
        let access_token = "";
        if (request?.user_switch_account == true) {
            const unlinkUnverifiedSocialMedia = await this.SocialMedias.findOne({
                relations: ['users'],
                where: {
                    social_user_name: Raw(alias => `LOWER(${alias}) = LOWER(:username)`, { username: request.social_user_name }),
                    social_type: request.social_media_type,
                    is_verified: false
                }
            });


            if (unlinkUnverifiedSocialMedia?.users) {
                if (unlinkUnverifiedSocialMedia.users.is_imported_by_admin == true) {
                    access_token = await this.switchUser(authUser, unlinkUnverifiedSocialMedia.users);
                    authUser = unlinkUnverifiedSocialMedia.users;
                }
                await this.SocialMedias.softDelete({ id: unlinkUnverifiedSocialMedia.id });
            }
        }

        switch (request.social_media_type) {
            case "youtube":
                await this.youtubeServices.youtube(request, authUser)
                break
            case "facebook":
                await this.facebookServices.facebook(request, authUser)
                break
            case "instagram":
                await this.instagramServices.instagram(request, authUser)
                //this.apifyService.instagramApify([request.social_user_name], 1);
                break
            case "tiktok":
                await this.tiktokService.tiktok(request, authUser)
                break
            case "instagram_facebook":
                await this.facebookServices.instagramFacebook(request, authUser)
                break
            default:
                throw new HttpException(responseMessages[lang].user.social_media.type_invalid, HttpStatus.BAD_REQUEST)
        }
        // UPDATE THE USER SLUG
        const slug = await this.generateSlug(request.social_user_name);
        this.Users.update(authUser.id, { slug: slug });
        if (authUser.image) {
            this.updateCometChatUser(authUser)
        }
        if (request?.id) {
            await this.unlinkAccount({ id: request.id }, { social_type: request.social_media_type }, authUser);
            // Add the new platform to the user's platforms
            const userPlatforms = await this.Users.findOne({
                where: { id: authUser.id },
            });

            const existingPlatforms: string[] = Array.isArray(userPlatforms?.platforms)
                ? userPlatforms.platforms
                : [];

            authUser.platforms = [
                ...new Set([
                    ...existingPlatforms,
                    request.social_media_type,
                ]),
            ];

            await this.Users.save(authUser);
        }

        return { access_token }
    }
    async updateCometChatUser(authUser) {
        try {
            let obj = {
                avatar: authUser.image
            }
            const COMET_CHAT_API_KEY = await this.encryptService.decrypt(process.env.COMET_CHAT_API_KEY);
            const headers = { accept: 'application/json', 'content-type': 'application/json', apikey: COMET_CHAT_API_KEY };
            await axios.put(process.env.COMET_CHAT_URL + 'users/' + authUser.id, obj, { headers });
        } catch (error: any) {
            this.errorLogService.logError('cometChat', error.name, error.message, { user_id: authUser.id });
            console.error("Error updating CometChat user:", error);
        }
    }

    async switchUser(authUser, switchUser) {

        try {
            const { id, ai_summary, ...authUserData } = authUser;
            Object.assign(switchUser, authUserData);
            switchUser.slug = await this.generateSlug(authUserData.first_name, authUserData.last_name);
            await this.Users.save(switchUser);
            //await this.Users.softDelete({ id: authUser.id });
            await this.userServices.deleteInfluencer(authUser);
            const payload = { sub: switchUser.id, username: switchUser.email };
            const COMET_CHAT_API_KEY = await this.encryptService.decrypt(process.env.COMET_CHAT_API_KEY);
            const headers = { accept: 'application/json', 'content-type': 'application/json', apikey: COMET_CHAT_API_KEY };
            // CREATE COMATE CHAT USER IF SWITCH USER
            const obj = {
                uid: switchUser.id,
                name: switchUser.display_name,
                withAuthToken: true
            }
            const response = await axios.post(process.env.COMET_CHAT_URL + 'users', obj, { headers });
            return await this.jwtService.sign(payload);
        } catch (error: any) {
            this.errorLogService.logError('switchUser', error.name, error.message, { user_id: authUser.id });
            console.error("Error during user switch:", error);
        }
    }
    async generateSlug(firstName, lastName = '') {

        // Generate initial slug from the name
        let slug = slugify(translitSlug(`${firstName} ${lastName}`), { lower: true, strict: true });

        // Check if the slug exists
        let existing = await this.Users.findOne({ where: { slug }, withDeleted: true });

        // If slug exists, append a 4-character random string
        if (existing) {
            const randomString = Math.random().toString(36).substring(2, 6); // Generate a 4-character random string
            slug = `${slug}-${randomString}`;
        }

        return slug;
    }

    async socialMediaEdit(params: any, request: SocialMediasEditDto, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }
        const { id } = params
        switch (request.social_media_type) {
            case "youtube":
                await this.youtubeServices.youtubeEdit(request, id)
                break
            case "facebook":
                await this.facebookServices.facebookEdit(request, id)
                break
            case "instagram":
                await this.instagramServices.instagramEdit(request, id)
                break
            case "tiktok":
                await this.tiktokService.tiktokEdit(request, id)
                break
            case "xiaohongshu":
                await this.xiaohongshuService.xiaohongshuEdit(request, id)
                break

            default:
                throw new HttpException(responseMessages[lang].user.social_media.type_invalid, HttpStatus.BAD_REQUEST)
        }
        return
    }

    async socialMediaLivePost(params, query) {
        const lang = "en"
        let socialMediaExists = { social_access_token: "" };
        if (query.platform != "facebook") {
            socialMediaExists = await this.SocialMedias.findOne({ where: { id: params.social_id } })

            if (!socialMediaExists) {
                throw new HttpException(responseMessages[lang].user.social_media.not_exists, HttpStatus.RESET_CONTENT)
            }
            if (!socialMediaExists.social_access_token) {
                throw new HttpException(responseMessages[lang].user.social_media.asscess_token_invalid, HttpStatus.BAD_GATEWAY)
            }
        }

        let response;
        switch (query.platform) {
            case "youtube":
                response = await this.youtubeServices.getLivePlayList(socialMediaExists, query.nextPageToken)
                break
            case "facebook":
                response = await this.facebookServices.getLivePost(params.social_id, query.nextPageToken)
                break
            case "instagram":
                response = await this.instagramServices.getLivePost(socialMediaExists, query.nextPageToken)
                break
            case "tiktok":
                response = await this.tiktokService.getLivePost(socialMediaExists, query.nextPageToken)
                break
            default:
                throw new HttpException(responseMessages[lang].user.social_media.type_invalid, HttpStatus.BAD_REQUEST)
        }

        if (response == false) {
            await this.SocialMedias.update({ id: params.social_id }, { is_token_expire: true })
            // throw new HttpException(responseMessages[lang].user.social_media.token_expire, HttpStatus.BAD_REQUEST)
        }

        return { data: response }
    }
    async extractPageIdFromUrl(url: string) {
        const match = url.match(/facebook\.com\/(\d+)\/posts\//);
        return match ? match[1] : null;
    }

    async updateCampaignPostsInsights() {
        const daysAgo = moment().subtract(Constants.CAMPAIGN_POST_SYNC_CRON_DAYS, 'days').toDate(); //, post_sync_cron_at: LessThanOrEqual(daysAgo)
        const campaigns = await this.Campaign.find({ where: { status: CampaignStatus.RUNNING, post_sync_cron_at: LessThanOrEqual(daysAgo) } });
        for (const campaign of campaigns) {
            campaign.post_sync_cron_at = new Date();
            await this.Campaign.save(campaign);
            let query = this.Posts.createQueryBuilder("posts")
                .innerJoin("posts.campaign", "campaign")
                .leftJoinAndSelect("posts.social_media", "social_media")
            query = query.andWhere("campaign.id = :campaign_id", { campaign_id: campaign.id });
            //  query = query.andWhere('posts.id= :post_id', { post_id: '95f692a3-41b8-44ce-8980-2190f606fed1' })
            const posts = await query.getMany();
            console.log("posts", posts.length);
            if (posts.length == 0) {
                continue;
            }
            for (const post of posts) {
                if (!post.social_media) {
                    continue;
                }
                let response;
                let division;
                switch (post.platform) {
                    case "youtube":
                        response = await this.youtubeServices.getSingleVideo(post.social_post_id)
                        if (!response) {
                            continue;
                        }
                        post.view_counts = response?.statistics?.viewCount || 0
                        post.like_counts = response?.statistics?.likeCount || 0
                        post.comment_count = response?.statistics?.commentCount || 0
                        division = Number(post.social_media.follower_count); // Avoid division by zero
                        if (division == 0) {
                            division = 1;
                        }
                        post.engagement_rate = parseFloat((((Number(post.like_counts) + Number(post.comment_count) + Number(post.view_counts)) / division * 100).toFixed(4)));
                        break
                    case "facebook":
                        const pageId = await this.extractPageIdFromUrl(post.post_link.toString())
                        response = await this.facebookServices.getSinglePost(pageId, post.social_post_id)
                        post.like_counts = response.reactions.summary.total_count || 0
                        post.comment_count = response.comments.summary.total_count || 0
                        division = Number(post.social_media.follower_count); // Avoid division by zero
                        if (division == 0) {
                            division = 1;
                        }
                        post.engagement_rate = parseFloat((((Number(post.like_counts) + Number(post.comment_count)) / Number(division) * 100).toFixed(4)));
                        break
                    case "instagram":
                        response = await this.instagramServices.getSinglePost(post.social_media, post.social_post_id)
                        if (!response) {
                            continue;
                        }
                        post.view_counts = response['view_count']
                        post.like_counts = response['like_count']
                        post.comment_count = response['comments_count']
                        division = Number(post.social_media.follower_count); // Avoid division by zero
                        if (division == 0) {
                            division = 1;
                        }
                        post.engagement_rate = parseFloat((((Number(post.like_counts) + Number(post.comment_count) + Number(post.view_counts)) / division * 100).toFixed(4)));
                        break
                    case "tiktok":
                        response = await this.tiktokService.getSingleVideo(post.social_media, post.social_post_id)
                        if (!response) {
                            continue;
                        }
                        post.view_counts = response['view_count']
                        post.like_counts = response['like_count']
                        post.comment_count = response['comment_count']
                        division = Number(post.social_media.follower_count); // Avoid division by zero
                        if (division == 0) {
                            division = 1;
                        }
                        post.engagement_rate = parseFloat((((Number(post.like_counts) + Number(post.comment_count) + Number(post.view_counts)) / division * 100).toFixed(4)));
                        break
                    default:
                        throw new HttpException(responseMessages.en.user.social_media.type_invalid, HttpStatus.BAD_REQUEST)
                }
                await this.Posts.save(post)
            }
        }
    }


    async socialMediaLink(query, user) {
        const { q } = query;
        let response;
        let platform;
        if (q.includes('facebook')) {
            platform = 'facebook'
            response = await this.facebookServices.getFacebookPostLink(q, user);
        } else if (q.includes('youtube') || q.includes('youtu.be')) {
            response = await this.youtubeServices.getYoutubeVideoLink(q, user)
            platform = 'youtube'
        } else if (q.includes('instagram')) {
            response = await this.instagramServices.getInstagramPostLink(q, user)
            platform = 'instagram'
        } else if (q.includes('tiktok')) {
            platform = 'tiktok'
        } else {
            throw new HttpException(responseMessages.en.user.social_media.type_invalid, HttpStatus.BAD_REQUEST)
        }
        return { data: response, platform }
    }

    /**
     * Unlinks a social media account from the user's profile based on the provided query and request parameters.
     *
     * @param query - An instance of UnlinkAccountQueryDto containing the social media account's unique identifier.
     * @param request - An instance of UnlinkAccountBodyDto specifying the type of social media to unlink.
     * @param authUser - The authenticated user object performing the unlink action.
     *
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @throws HttpException - Throws a 400 error if the specified social media account does not exist.
     * @throws HttpException - Throws a 400 error if the social media type is invalid.
     *
     * After unlinking, the user's total followers and following counts are decreased accordingly.
     */
    async unlinkAccount(query: UnlinkAccountQueryDto, request: UnlinkAccountBodyDto, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        const socialMediaExists = await this.SocialMedias.findOne({ where: { id: query.id, users: { id: authUser.id } } })
        if (!socialMediaExists) {
            throw new HttpException(responseMessages[lang].user.social_media.not_exists, HttpStatus.BAD_REQUEST)
        }

        switch (request.social_type) {
            case "youtube":
                await this.youtubeServices.unlinkYoutube(socialMediaExists)
                break
            case "facebook":
                await this.facebookServices.unlinkFacebook(socialMediaExists)
                break
            case "instagram":
                await this.instagramServices.unlinkInstagram(socialMediaExists)
                break
            case "tiktok":
                await this.tiktokService.unlinkTiktok(socialMediaExists)
                break
            case "xiaohongshu":
                await this.xiaohongshuService.unlinkXiaohingshu(socialMediaExists)
                break
            case "instagram_facebook":
                await this.instagramServices.unlinkInstagramFacebook(socialMediaExists)
                break
            default:
                throw new HttpException(responseMessages[lang].user.social_media.type_invalid, HttpStatus.BAD_REQUEST)
        }
        // DECRESE FOLLOWER & FOLLOWING COUNT ON UNLINK ACCOUNT

        const platforms = existsUser.platforms.filter((platform) => platform !== request.social_type)
        await this.Users.update(authUser.id, { platforms: platforms })
        return
    }

    /**
     * Sets the pending_steps field of the user to 1.
     * This is the first step of the influencer registration process.
     * @param authUser The authenticated user object performing the first step.
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @returns The user object with modified pending_steps field.
     */
    async firstStep(body, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        existsUser["pending_steps"] = 1
        // existsUser['platforms'] = body.platforms;
        await this.Users.save(existsUser)
        this.commonService.cometChatEmailNotification(existsUser.id);
        return await this.userServices.getUserDetails(authUser, authUser);
    }

    /**
     * Sets the pending_steps field of the user to 2.
     * This is the second step of the influencer registration process.
     * @param request - An instance of SecondStepDto containing the category_ids of the categories to be linked to the user.
     * @param authUser The authenticated user object performing the second step.
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @throws HttpException - Throws a 400 error if the user is already on a different registration page.
     * @returns The user object with modified pending_steps field.
     */
    async secondStep(request: SecondStepDto, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        if (existsUser.pending_steps != 1) {
            throw new HttpException(responseMessages[lang].user.invalid_registration_page, HttpStatus.NOT_FOUND)
        }

        await this.influencerRegisterRepository.updateInfluencerCategory(request, authUser)
        existsUser["pending_steps"] = 2
        await this.Users.save(existsUser)
        return await this.userServices.getUserDetails(authUser, authUser);
    }

    /**
     * Sets the pending_steps field of the user to 3.
     * This is the third and final step of the influencer registration process.
     * @param request - An instance of ThirdStepDto containing the industries to be linked to the user.
     * @param authUser The authenticated user object performing the third step.
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @throws HttpException - Throws a 400 error if the user is already on a different registration page.
     * @returns The user object with modified pending_steps field.
     */
    async thirdStep(request: ThirdStepDto, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        if (existsUser.pending_steps != 2) {
            throw new HttpException(responseMessages[lang].user.invalid_registration_page, HttpStatus.NOT_FOUND)
        }

        // await this.influencerRegisterRepository.createBrandIndustries(request,existsUser);

        existsUser["pending_steps"] = 3
        await this.Users.save(existsUser)

        const welcomeMailNotificationSetting = notificationSettings.welcome_email;
        if (welcomeMailNotificationSetting.email) {
            const name = `${existsUser.first_name} ${existsUser.last_name}`
            const mailSubject = emailMessages.en.welcome_mail.subject
            const mailObj = {
                hello_user_name: emailMessages.en.hello_user_name.replace(":user_name", name),
                main_title: emailMessages.en.welcome_mail.title,
                descriptions: emailMessages.en.welcome_mail.description,
                copyright: emailMessages.en.copyright,
                all_rights_reserved: emailMessages.en.all_rights_reserved
            }

            this.sendMailService.sendMailObjectWithTemplates(existsUser.email, mailSubject, "welcome_mail", mailObj)
        }
        return await this.userServices.getUserDetails(authUser, authUser);
    }

    async backStep(authUser: any) {
        authUser["pending_steps"] = authUser["pending_steps"] - 1
        await this.Users.save(authUser)
        return await this.userServices.getUserDetails(authUser, authUser);
    }

    /**
     * Updates the influencer data based on the provided request data.
     * @param params - An instance of InfluencerSlugParamDto containing the influencer slug to be updated.
     * @param request - An instance of InfluencerUpdateDto containing the influencer information to be updated.
     * @param response - The response object for sending the HTTP response.
     * @param req - The request object, containing the authenticated user information.
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @returns 201 status if the update is successful.
     * In case of an error, logs the error and responds with the respective error status and message.
     */
    async influencerUpdate(params: InfluencerSlugParamDto, request: InfluencerUpdateDto, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ slug: params.influencer_slug, role: UserRoles.INFLUENCER }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        if (request.phone_number) {
            const phoneNumberExists = await this.Users.createQueryBuilder('user')
                .where('user.phone_number = :phone_number', { phone_number: request.phone_number })
                .andWhere('user.is_whatsapp_verified = true')
                .andWhere('user.id != :id', { id: existsUser.id })
                .getOne();
            if (phoneNumberExists) {
                throw new HttpException(responseMessages[lang].user.phone_number_already_exists, HttpStatus.NOT_FOUND);
            }
        }

        const existingDisplayName = existsUser.display_name;
        // if (request?.display_name) {
        //     const displayNameExists = await this.Users.findOne({
        //         where: {
        //             display_name: Raw(alias => `LOWER(${alias}) = LOWER(:display_name)`, { display_name: request.display_name }),
        //             id: Not(existsUser.id)
        //         }
        //     });
        //     if (displayNameExists) {
        //         throw new HttpException(responseMessages[lang].user.display_name_already_exists, HttpStatus.BAD_REQUEST);
        //     }
        // }
        if (existsUser.phone_number !== request.phone_number) {
            existsUser['is_whatsapp_verified'] = null;
            existsUser['whatsapp_request_at'] = new Date();
            let phoneNumber = request.phone_number
            if (phoneNumber.startsWith('0')) {
                phoneNumber = phoneNumber.substring(1);
            }
            phoneNumber = `${request.country_code}${phoneNumber}`.replace('+', '');
            this.whatsappServices.verifyWhatsAppNumber(phoneNumber, existsUser.first_name);
        }
        existsUser["first_name"] = request.first_name;
        existsUser["last_name"] = request.last_name;
        existsUser["country_code"] = request.country_code;
        existsUser["phone_number"] = request.phone_number;
        existsUser['country'] = request.country;
        existsUser['gender'] = request.gender;
        existsUser['currency'] = request.currency;
        existsUser['is_updated_by_cron'] = request.is_updated_by_cron;
        existsUser['about_me'] = request.about_me;
        existsUser['display_name'] = request.display_name;
        existsUser['whatsapp_phone_number'] = `${request.country_code}${request.phone_number}`.replace('+', '');

        if (request.category_ids.length > 0) {
            const settings = await this.Settings.find({ where: { type: In(["category_min", "category_max"]) } })
            const categoryLimits = {
                category_min: Number(settings.find((setting) => setting.type === "category_min")?.value),
                category_max: Number(settings.find((setting) => setting.type === "category_max")?.value)
            }

            // if (request.category_ids.length >= categoryLimits.category_min && request.category_ids.length <= categoryLimits.category_max) {

            // }

            await this.influencerRegisterRepository.updateInflucnerKeywords(request, existsUser)
            await this.influencerRegisterRepository.updateInfluencerCategory(request, existsUser)
        }


        await this.Users.save(existsUser)

        if (request.display_name !== existingDisplayName) {
            this.campaignRepository.updateCometChatInfluencerGroup(existsUser.id);
        }

        const data = { display_name: request.display_name, first_name: existsUser.first_name, last_name: existsUser.last_name };
        return { data };
    }

    async influencerKeywords(params: InfluencerSlugParamDto, request: InfluencerKeywords, authUser: any) {
        const lang = authUser.language || "en"
        const existsUser = await this.Users.findOne({ where: [{ slug: params.influencer_slug, role: UserRoles.INFLUENCER }] })
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND)
        }

        await this.influencerRegisterRepository.updateInflucnerKeywords(request, authUser)

        return
    }

    async saveBank(body: BankAccountDto, authUser: any) {
        const bankDetails = {
            influencer: authUser,
            holder_name: body.holder_name,
            account_number: body.account_number,
            qr_code: body.qr_code
        };

        await this.BankDetails.save(bankDetails);
        return;
    }

    async updateBank(params: BankIdDto, body: BankAccountDto, authUser: any) {

        const bankDetails = await this.BankDetails.findOne({ where: { id: params.id, influencer: { id: authUser.id } } });
        if (!bankDetails) {
            throw new HttpException(responseMessages[authUser.language].user.bank_not_exists, HttpStatus.NOT_FOUND)
        }

        bankDetails.account_number = body.account_number
        bankDetails.qr_code = body.qr_code
        bankDetails.holder_name = body.holder_name

        await this.BankDetails.save(bankDetails);
        return;
    }
}
