import { Injectable, HttpException, HttpStatus, Res } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, Not } from 'typeorm';
import { classToPlain } from 'class-transformer';
import { responseMessages } from '../../messages/response-messages';
import { emailMessages } from '../../messages/email-messages';
import { AdminRepository } from './admin.repository';
import * as bcrypt from 'bcryptjs';
import { Constants } from '../../common/constants';
import { UsersServices } from 'src/common/services/users/users.service';
import { CommonService } from 'src/modules/common/common.services';
// const commonService = new CommonService(re);

// Entities Files
import { UserRoles, Users } from "../../entities/users.entity";
import { UserDetailsQueryDto } from './dtos/user-details-query.dto';
import { SocialMediaPostQuery } from './dtos/social-meida-list-query.dto';
import { YoutubeServices } from 'src/common/services/youtube/youtube.service';
import { FacebookServices } from 'src/common/services/facebook/facebook.service';
import { InstagramServices } from 'src/common/services/instagram/instagram.service';
import { SendMailService } from 'src/common/config/send-mail.service';
import { TiktokServices } from 'src/common/services/tiktok/tiktok.service';
import { UserSlugParamDto } from './dtos/user-slug-param.dto';
import { ImportUsersDto } from './dtos/import-users.dto';
import { SocialMediaPosts } from 'src/entities/social-media-posts.entity';
import { CampaignInfluencerBookmarks } from 'src/entities/campaign_influencer_bookmark.entity';
import { BrandFavorite } from 'src/entities/brand-favorit.entity';
import { CurrencyRate } from 'src/entities/currency_rates.entity';
import { CurrencyExchangeUpdateDto } from './dtos/currency-rate-update.dto';
import { EncryptionService } from 'src/common/services/encryption/encryption.service';
import { CampaignInfluencer } from 'src/entities/campaign_influencer.entity';
import e from 'express';
import { first } from 'rxjs';
import { Plan } from 'src/entities/plan.entity';

@Injectable()
export class AdminService {

    constructor(
        private adminRepository: AdminRepository,
        private usersServices: UsersServices,
        private youtubeServices: YoutubeServices,
        private facebookServices: FacebookServices,
        private instagramServices: InstagramServices,
        private sendMailService: SendMailService,
        private tiktokService: TiktokServices,
        private commonService: CommonService,
        private encryptionService: EncryptionService,
        @InjectRepository(Users)
        private Users: Repository<Users>,

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

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

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

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

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

    ) { }

    async userList(queryParams: any, authUser: any) {
        const page = queryParams.page - 1;
        const pageSize = queryParams.per_page ? queryParams.per_page : Constants.brand_users_list;
        const offset = page * pageSize;
        const nextPage = page + 1;
        const nextOffset = nextPage * pageSize;

        let sortByArr = {
            created_at: 'users.created_at',
            first_name: 'users.first_name',
            email: 'users.email',
            total_followers: 'users.total_followers',
            engagement_ratio: 'users.engagement_ratio',
            is_active: 'users.is_active',
            display_name: 'users.display_name',
        };

        let sortBy = queryParams.sort_by || 'created_at';
        let sortType = queryParams.sort || 'DESC';
        sortBy = sortByArr[sortBy];

        const data = await this.usersServices.getUsersList(queryParams, sortBy, sortType, pageSize, offset);

        return {
            data: data.results,
            total: data.total,
            hasMoreResults: (data.total > nextOffset) ? 1 : 0,
        }

    }

    async adminEdit(params, request) {
        const existsUser = await this.Users.findOne({ where: [{ slug: params.slug, role: UserRoles.ADMIN }] });
        if (!existsUser) {
            throw new HttpException(responseMessages.en.user.user_not_exists, HttpStatus.NOT_FOUND);
        }
        Object.assign(existsUser, request);
        await this.Users.save(existsUser);
        return;
    }

    /**
     * Retrieves a user details based on user id.
     */
    async userDetails(params: UserDetailsQueryDto, authUser: any, queryParam: any) {
        const lang = authUser.language || 'en';
        const existsUser = await this.Users.findOne({ where: { slug: params.slug }, withDeleted: true });

        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND);
        }
        const data = await this.usersServices.getUserDetails(existsUser, authUser);

        if (authUser.role == 'brand') {
            if (queryParam.campaign_id) {
                data['campaignBookmarks'] = await this.CampaignInfluencerBookmarks.find({ where: [{ campaign: { id: queryParam.campaign_id }, influencer: { id: data.id } }] });
                data['isBookmarkAdded'] = data.campaignBookmarks.length > 0 ? 1 : 0;
                data['isCampaignAdded'] = await this.CampaignInfluencer.count({ where: [{ campaign: { id: queryParam.campaign_id }, influencer: { id: data.id } }] });
            }

            data.favoritesCount = await this.BrandFavorite.count({ where: [{ brand: { id: authUser.id }, influencer: { id: data.id } }] });
        }
        if (existsUser.role == 'brand') {
            data['opposite_plan'] = await this.Plan.findOne({ where: { id: Not(data.subscription[0].plan.id) } });
        }
        return {
            data: data,
        }
    }

    async getSocialMediaPosts(query: SocialMediaPostQuery, authUser: any) {
        // const lang = authUser.language || 'en';
        let data = null;
        switch (query.social_type) {
            case 'youtube':
                data = await this.youtubeServices.getChannelVideos(query.post_id);
                break;
            case 'facebook':
                data = await this.facebookServices.getFacebookPosts(query.post_id);
                break;
            case 'instagram':
                data = await this.instagramServices.getInstagramMediasFromDB(query.post_id);
                break;
            case 'tiktok':
                data = await this.tiktokService.gettikTokVideosFromBD(query.post_id);
                break;
            default:
                throw new HttpException(responseMessages.en.user.social_media.type_invalid, HttpStatus.BAD_REQUEST);
        }
        return { data };
    }

    /**
     * Updates the user activation status based on the request.
     * @param params - An instance of UserSlugParamDto containing the user slug to be updated.
     * The request, if user activation status is active than its inactive or if user activation status is inactive then its make active.
     * @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 activationStatusUpdate(params: UserSlugParamDto, authUser: any) {
        const lang = authUser.language || 'en';
        const existsUser = await this.Users.findOne({ where: { slug: params.slug } });
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND);
        }

        existsUser['is_active'] = existsUser.is_active == true ? false : true;
        await this.Users.save(existsUser);

        return;
    }




    async storeFileManager(fileName: string) {
        let fileMangerCreate = {
            file_name: fileName,
            extension: fileName.split('.').pop(),
            source_from: 'Modash',
            file_path: `files/user-excel/${fileName}`,
        }

        const fileManeger = await this.adminRepository.createFileManagerwithObject(fileMangerCreate);

        return fileManeger;
    }


    async dashboard(params: any) {
        const countObject = await this.adminRepository.getDashboardCount(params);
        return { countObject }
    }

    async dashboardChart(params) {
        const getRevenueLineChart = await this.adminRepository.getRevenueLineChart(params);
        return { getRevenueLineChart }
    }

    async currencyExchangeList() {
        return { data: await this.CurrencyRate.find() }
    }


    async currencyExchangeUpdate(request: CurrencyExchangeUpdateDto) {
        if (request.request_array.length > 0) {
            for await (const req of request.request_array) {
                await this.CurrencyRate.update(req['id'], { rate: req['rate'] });
            }
        }
        return;
    }

    async encryptionKey(request) {
        return await this.encryptionService.encrypt(request.value);
    }
}
