import { HttpService } from "@nestjs/axios";
import { Injectable, Logger } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import mongoose from "mongoose";
import { JwtService } from '@nestjs/jwt';
import { CurrencyValuation } from "src/models/CurrencyValuation.schema";
import { CurrencyList } from "src/constant/CountryCodeToCurrency";
import { lastValueFrom, map } from "rxjs";
import { AnalyticsReport, recordTypeEnum } from "src/models/AnalyticsReport.schema";
import * as moment from "moment";
import * as fs from 'fs';
import * as zlib from 'zlib'
import { parse } from 'csv-parse'
import { AppleAccount } from "src/models/AppleAccount.schema";
import { EventEmitter2 } from "@nestjs/event-emitter";
import { AnalyticsReportService } from "./AnalyticsReport.service";
import { CurrentStage } from "../enum/CurrentStage.enum";
import { Cron, CronExpression } from '@nestjs/schedule';
import * as path from 'path';

@Injectable()
export class CronSyncService {

    CONST_REPORT_TYPES = {
        SALES: 'SALES',
        DOWNLOAD: 'DOWNLOAD'
    }
    APPLEDATEFORMAT = "YYYY-MM-DD"
    DATEFORMAT = "DD-MM-YYYY"

    constructor(
        @InjectModel("CurrencyValuation") private CurrencyValuationRepo: mongoose.Model<CurrencyValuation>,
        @InjectModel("AnalyticsReport") private analyticsReportRepo: mongoose.Model<AnalyticsReport>,
        @InjectModel("AppleAccount") private AppleAccountRepo: mongoose.Model<AppleAccount>,
        private analyticsService: AnalyticsReportService,
        private eventEmitter: EventEmitter2,
        private readonly httpService: HttpService,
        private jwtService: JwtService,
    ) { }
    private readonly logger = new Logger(CronSyncService.name);

    // @Cron(CronExpression.EVERY_5_MINUTES) // Runs daily at 2:00 AM
    // async handleDailyAppleReportsSync() {
    //     const vendors = await this.AppleAccountRepo.find({});
    //     const fromDate = moment().subtract(2, 'days').startOf('day').toDate(); // Normalize date
    //     const reportTypes = [recordTypeEnum.SALES, recordTypeEnum.DOWNLOAD];

    //     for (const vendor of vendors) {
    //         for (const reportType of reportTypes) {
    //             try {
    //                 // Atomic operation to prevent duplicates
    //                 const existingOrInserted = await this.analyticsReportRepo.findOneAndUpdate(
    //                     {
    //                         AccountID: vendor._id,
    //                         EventDate: fromDate,
    //                         type: reportType,
    //                     },
    //                     {
    //                         $setOnInsert: {
    //                             AccountID: vendor._id,
    //                             EventDate: fromDate,
    //                             type: reportType,
    //                             // Add any initial data you want here
    //                             syncedAt: new Date(),
    //                         },
    //                     },
    //                     { upsert: true, new: false } // new: false => returns old doc if exists
    //                 );

    //                 if (existingOrInserted) {
    //                     console.log(`⚠️ Already synced: ${vendor.VendorID} [${reportType}] on ${moment(fromDate).format('YYYY-MM-DD')}`);
    //                 } else {
    //                     const syncResult = await this.doSyncAnalyticsReport(reportType, moment(fromDate).format('YYYY-MM-DD'), vendor);
    //                     console.log(`✅ Synced ${reportType} for Vendor ${vendor.VendorID}:`, syncResult?.count || 0);
    //                 }
    //             } catch (err) {
    //                 console.error(`❌ Sync failed for ${vendor.VendorID} [${reportType}]`, err);
    //             }
    //         }
    //     }
    // }

    // this crone is  perfectly running for staging server....
    @Cron(CronExpression.EVERY_DAY_AT_7PM) // Runs every day at 2:00 AM
    async handleDailyAppleReportsSync() {
        try {
            const vendors = await this.AppleAccountRepo.find({});
            const fromDate = moment().subtract(2, 'days').format('YYYY-MM-DD');
            const reportTypes = [recordTypeEnum.SALES, recordTypeEnum.DOWNLOAD];

            for (const vendor of vendors) {
                for (const reportType of reportTypes) {
                    const alreadySynced = await this.analyticsReportRepo.findOne({
                        AccountID: vendor._id,
                        EventDate: new Date(fromDate),
                        type: reportType
                    });

                    if (!alreadySynced) {
                        try {
                            const syncResult = await this.doSyncAnalyticsReport(reportType, fromDate, vendor);
                            console.log(`✅ Synced ${reportType} for Vendor ${vendor.VendorID}:`, syncResult?.count || 0);
                        } catch (err) {
                            console.error(`❌ Sync failed for ${vendor.VendorID} [${reportType}]`, err);
                        }
                    } else {
                        console.log(`⚠️ Already synced: ${vendor.VendorID} [${reportType}] on ${fromDate}`);
                    };
                };
            };
        } catch (error) {
            console.log(error, 'error......');
        };
    };

    // this cron  is  particulaer  date range  
    // @Cron(CronExpression.EVERY_MINUTE)
    // async handleDailyAppleReportsSync() {
    //     try {
    //         const vendors = await this.AppleAccountRepo.find({});
    //         const reportTypes = [recordTypeEnum.SALES, recordTypeEnum.DOWNLOAD];

    //         // 👉 Manually define the dates you want to sync
    //         const datesToSync = ['2025-07-24', '2025-07-25'];

    //         for (const vendor of vendors) {
    //             for (const reportType of reportTypes) {
    //                 for (const dateStr of datesToSync) {
    //                     const alreadySynced = await this.analyticsReportRepo.findOne({
    //                         AccountID: vendor._id,
    //                         EventDate: new Date(dateStr),
    //                         type: reportType
    //                     });

    //                     if (!alreadySynced) {
    //                         try {
    //                             const syncResult = await this.doSyncAnalyticsReport(reportType, dateStr, vendor);
    //                             console.log(`✅ Synced ${reportType} for Vendor ${vendor.VendorID} on ${dateStr}:`, syncResult?.count || 0);
    //                         } catch (err) {
    //                             console.error(`❌ Sync failed for ${vendor.VendorID} [${reportType}] on ${dateStr}`, err);
    //                         }
    //                     } else {
    //                         console.log(`⚠️ Already synced: ${vendor.VendorID} [${reportType}] on ${dateStr}`);
    //                     }
    //                 }
    //             }
    //         }
    //     } catch (error) {
    //         console.error('❌ Error in handleDailyAppleReportsSync:', error);
    //     }
    // }


    // @Cron(CronExpression.EVERY_MINUTE)
    // async handleDailyAppleReportsSync() {
    //     try {


    //     console.log('cron running ...............');

    //     const vendors = await this.AppleAccountRepo.find({});
    //     console.log(vendors,'vendors............');

    //     const reportTypes = [recordTypeEnum.SALES, recordTypeEnum.DOWNLOAD];
    //     console.log(recordTypeEnum,'tyieisjw');

    //     for (const vendor of vendors) {
    //         console.log('vendorlooppppp first');

    //         for (const reportType of reportTypes) {
    //             console.log('second loopssssss');

    //             // 1. Check last synced date
    //             const lastSynced = await this.analyticsReportRepo.findOne(
    //                 { AccountID: vendor._id, type: reportType },
    //                 { sort: { EventDate: -1 }, projection: { EventDate: 1 } }
    //             );
    //             console.log(lastSynced,'lasyynejvykok');


    //             const maxAppleAvailableDate = moment().subtract(2, 'days'); // Apple thi max etlu j male

    //             // 2. Start from lastSynced + 1, fallback to 7 days ago
    //             let startDate = lastSynced
    //                 ? moment(lastSynced.EventDate).add(1, 'day')
    //                 : moment().subtract(7, 'days');

    //             // 3. Don't go beyond max available date
    //             const endDate = maxAppleAvailableDate;

    //             while (startDate.isSameOrBefore(endDate)) {
    //                 const syncDate = startDate.format('YYYY-MM-DD');

    //                 const alreadyExists = await this.analyticsReportRepo.findOne({
    //                     AccountID: vendor._id,
    //                     EventDate: new Date(syncDate),
    //                     type: reportType,
    //                 });

    //                 if (!alreadyExists) {
    //                     try {
    //                         const syncResult = await this.doSyncAnalyticsReport(reportType, syncDate, vendor);
    //                         console.log(`✅ Synced ${reportType} for ${vendor.VendorID} on ${syncDate}:`, syncResult?.count || 0);
    //                     } catch (err) {
    //                         console.error(`❌ Sync failed for ${vendor.VendorID} [${reportType}] on ${syncDate}`, err);
    //                     }
    //                 } else {
    //                     console.log(`⚠️ Already exists ${reportType} for ${vendor.VendorID} on ${syncDate}`);
    //                 }
    //                 startDate = startDate.add(1, 'day');
    //             }
    //         }
    //     }
    //     } catch (error) {
    //         console.log(error,'error');
    //     }
    // }

    // this  cron  is specifc retrive  data using the vendor  id 
    // @Cron(CronExpression.EVERY_5_MINUTES)
    // async handleDailyAppleReportsSync() {
    //     try {
    //         const targetVendorID = '89623384'; // Replace with actual VendorID
    //         const vendor = await this.AppleAccountRepo.findOne({ VendorID: targetVendorID });
    //         console.log(vendor, 'vendormmmmmmmmmmmmm');


    //         if (!vendor) {
    //             console.error(`❌ Vendor with ID ${targetVendorID} not found`);
    //             return;
    //         }

    //         const reportTypes = [recordTypeEnum.SALES, recordTypeEnum.DOWNLOAD];

    //         // 👉 Define date range
    //         const fromDate = moment('2025-06-26');
    //         const toDate = moment('2025-07-26');

    //         for (let date = fromDate.clone(); date.isSameOrBefore(toDate); date.add(1, 'day')) {
    //             const dateStr = date.format('YYYY-MM-DD');

    //             for (const reportType of reportTypes) {
    //                 const alreadySynced = await this.analyticsReportRepo.findOne({
    //                     AccountID: vendor._id,
    //                     EventDate: new Date(dateStr),
    //                     type: reportType
    //                 });

    //                 if (!alreadySynced) {
    //                     try {
    //                         const syncResult = await this.doSyncAnalyticsReport(reportType, dateStr, vendor);
    //                         console.log(`✅ Synced ${reportType} for Vendor ${vendor.VendorID} on ${dateStr}:`, syncResult?.count || 0);
    //                     } catch (err) {
    //                         console.error(`❌ Sync failed for ${vendor.VendorID} [${reportType}] on ${dateStr}`, err);
    //                     }
    //                 } else {
    //                     console.log(`⚠️ Already synced: ${vendor.VendorID} [${reportType}] on ${dateStr}`);
    //                 }
    //             }
    //         }
    //     } catch (error) {
    //         console.error('❌ Error in handleDailyAppleReportsSync:', error);
    //     };
    // };


    async doSyncCountryWisevaluation() {
        console.log(CurrencyList?.length)
        return await new Promise(async (resolve, reject) => {
            const requests = CurrencyList.map((item, index) => this.convertCurrencyValue(item, "usd"))
            try {
                const result = await Promise.all(requests);
                result.map(({ status, value, from, to }) => {
                    if (status == true && value) {
                        if (status == true) {
                            this.CurrencyValuationRepo.create({
                                currencyBase: "USD",
                                rates: value,
                                currency: from,
                                syncDate: new Date(),
                                createdAt: new Date(),
                            })
                        }
                    }
                });
                resolve({ status: true })
            }
            catch (error) {
                console.log(error)
                resolve({ status: false, error: JSON.stringify(error) })
            }

        })

    }

    async doSyncReportInBatch(from, to, type, applevendor = null) {
        console.log("called")
        const dates = await this.enumerateDaysBetweenDates(from, to)

        const totalDates = dates?.length
        const recordsBetweenDates = await this.analyticsReportRepo.aggregate([
            {
                $match: {
                    EventDate: {
                        $gte: new Date(from),
                        $lte: new Date(to)
                    },
                    type: type.toUpperCase(),
                },
            },
            {
                $group: {
                    _id: { $dateToString: { format: "%Y-%m-%d", date: "$EventDate" } }
                }
            },
            {
                $project: {
                    _id: 0,
                    date: "$_id"
                }
            },
            {
                $group: {
                    _id: null,
                    dates: { $push: "$date" }
                }
            }
        ]);
        let filteredDates = []
        if (recordsBetweenDates?.length) {
            const datedRecords = recordsBetweenDates?.length ? recordsBetweenDates[0].dates.sort() : dates
            dates.forEach((elemnt) => {
                if (!datedRecords?.includes(elemnt)) {
                    filteredDates.push(elemnt)
                }
            })
        } else {
            console.log(">>>>>>>>>>>elseeeeeeeee>>>>>>>>>>>");
            filteredDates = dates
        }
        const requests = filteredDates.map((item, index) => this.doSyncAnalyticsReport(type, item, applevendor))
        console.log("--------TOTAL REQUEST:", requests?.length)
        console.log("RESOLVD------")
        const result = await Promise.all(requests);

        console.log("SYNCED")
        let sum = 0
        result.map((i) => {
            if (i?.count) {
                sum += i?.count
            }
        })
        return { status: true, count: sum, result }
    }

    // @OnEvent('AutomaticSync.Report')
    async doHandleSyncReportInBatchAfterCredsSync(vendorID) {
        console.log("IN EVENT for Syncing Batch Vendor Id", vendorID)
        const fromDate = moment().subtract(60, 'd').format('YYYY-MM-DD');
        const toDate = moment().subtract(7, 'd').format('YYYY-MM-DD');
        let syncArr = []
        // syncArr.push(this.doSyncReportInBatch(fromDate,toDate,recordTypeEnum.SALES,vendorID))
        // syncArr.push(this.doSyncReportInBatch(fromDate,toDate,recordTypeEnum.DOWNLOAD,vendorID))

    }

    async doSyncAnalyticsReport(ReportTYPE, date, applevendor = null): Promise<{
        status: boolean,
        count?: number,
        error?: any,
        data?: any[],
    }> {
        if (ReportTYPE !== recordTypeEnum.SALES && ReportTYPE !== recordTypeEnum.DOWNLOAD) {
            return { status: false }
        }

        const hitDate = !!date == true ? moment(date).format('YYYY-MM-DD') : moment()

        if (moment(hitDate).format("DD-MM-YYYY") == moment().format("DD-MM-YYYY")) {
            moment(hitDate).add(-3, 'days')
        }
        const baseUrl = await this.doGetReportsUrl(ReportTYPE, hitDate, applevendor)
        console.log("CALLIED----", hitDate)

        return await new Promise((resolve, reject) => {
            this.doFetchReports(baseUrl, applevendor).then((response) => {
                if (response?.status) {
                    console.log("CALLING----", hitDate)
                    this.doHandleDataExtractionFromZIP(response.data, hitDate, ReportTYPE, applevendor).then(async (extractedData) => {
                        if (extractedData?.status == true) {
                            // resolve({ status: false, error: err })
                            console.log("SAVING----", hitDate, extractedData.data?.length)
                            this.analyticsReportRepo.insertMany(extractedData.data)
                            console.log("RESOLVING------")
                            resolve(extractedData)
                        }
                    })
                }
                if (response?.status == false) {
                    if (response.code == 401) {
                        return {
                            status: false,
                            code: response.code,
                            message: response.message
                        }
                    }
                    if (response.code == 404) {
                        resolve(response)
                    }
                }
            })
        })
    }

    async doSyncHealth() {
        return {
            status: true,
            code: 200,
            message: 'success'
        }
    }

    async doHandleAccountsSyncing(file) {
        let results = []
        let jsonRecords = []
        const result: any = await new Promise((resolve, reject) => {
            fs.createReadStream(file.path)
                .pipe(parse({ delimiter: ',' }))
                .on('data', (data) => results.push(data))
                .on('end', async () => {
                    const fromDate = moment().subtract(60, 'd').format('YYYY-MM-DD');
                    const toDate = moment().subtract(2, 'd').format('YYYY-MM-DD');
                    // const fromDate = moment('2024-06-01').format('YYYY-MM-DD');
                    // const toDate = moment('2024-06-20').format('YYYY-MM-DD');
                    let requestArr = []
                    let vendorsInStack = []
                    for (let i = 1; i < results.length; i++) {
                        const element = results[i];
                        let tempArr: any = {}
                        for (let jindex = 0; jindex < element.length; jindex++) {
                            const jElement = element[jindex];
                            tempArr[results[0][jindex].replace(/\s+/g, '')] = jElement
                        }
                        let record = await this.AppleAccountRepo.findOne({
                            VendorID: tempArr.VenderID
                        })
                        if (record) {
                            await this.AppleAccountRepo.updateMany(
                                {},
                                { $set: { InitialSyncStatus: CurrentStage.INPROGRESS } }
                            )
                            await this.AppleAccountRepo.updateOne({ VendorID: record.VendorID }, { $set: { AccountName: tempArr.AccountName } })
                        }
                        if (!vendorsInStack.includes(tempArr.VenderID)) {
                            if (!record) {
                                record = await this.AppleAccountRepo.create({
                                    AccountName: tempArr.AccountName,
                                    Issuer: tempArr.Issuer,
                                    KeyId: tempArr.KeyID,
                                    PrivateKey: tempArr.PrivateKey,
                                    VendorID: tempArr.VenderID,
                                    InitialSyncStatus: CurrentStage.INPROGRESS,
                                    SyncDate: new Date()
                                })
                            }
                            this.eventEmitter.emit('sync.Report', fromDate, toDate, record)
                            // this.eventEmitter.emit('sync.Report', fromDate, toDate, record)

                            // requestArr.push(this.doSyncReportInBatch(fromDate, toDate, recordTypeEnum.DOWNLOAD, record))
                            // requestArr.push(this.doSyncReportInBatch(fromDate, toDate, recordTypeEnum.SALES, record))
                            jsonRecords.push(record)
                            vendorsInStack.push(tempArr.VenderID)
                        }
                    }
                    // await Promise.all(requestArr)
                    console.log(requestArr, "reqqarrry>>>>>>>>>>>>>>>>>>");
                    resolve({ data: [], status: true })
                    fs.unlinkSync(file.path);
                }).on("error", () => {
                    resolve({ data: null, status: false })
                });
        })
        if (result.status == true) {
            return {
                data: await this.AppleAccountRepo.find({}, {
                    VendorID: true,
                    AccountName: true,
                }),
                status: true
            }
            // const data = await this.AppleAccountRepo.find({}, {
            //     VendorID: true,
            //     AccountName: true,
            // });

            // const updateResult = await this.AppleAccountRepo.updateMany(
            //     {},
            //     { $set: { InitialSyncStatus: CurrentStage.COMPLETED } }
            // );

            // return {
            //     data: data,
            //     status: true
            // }
        }

        if (result.status == false) {
            return result
        }
    }

    async doSyncReportBatch(from, to, type, applevendor = null) {
        let syncRecord = await this.analyticsReportRepo.aggregate([
            {
                $match: {
                    EventDate: {
                        $gte: new Date(new Date(from)),
                        $lte: new Date(new Date(to)),
                    },
                    type: type.toUpperCase(),
                },
            },
            {
                $group: {
                    _id: {
                        $dateToString: { format: "%Y-%m-%d", date: "$EventDate" }
                    },
                    doc: { $first: "$$ROOT" }
                }
            },
            {
                $replaceRoot: { newRoot: "$doc" }
            }
        ])
        return syncRecord
    }

    doFetchVendors = async () => {
        return {
            data: await this.AppleAccountRepo.find({}, {
                VendorID: true,
                AccountName: true
            }),
            status: true
        }
    }

    async doHandleDataExtractionFromZIP(FILE, hitDate, ReportTYPE, appleVendor = null): Promise<{
        status: boolean,
        count?: number,
        error?: any,
        data: any[]
    }> {
        const timestamp = moment().unix()
        const filePath = "public/tempReports/" + timestamp + + '_sr.gz';
        fs.writeFileSync(filePath, FILE);
        const decompressedDataString = await zlib?.gunzipSync(FILE)?.toString('utf-8');
        return await new Promise(async (resolve, reject) => {
            parse(decompressedDataString, { delimiter: '\t' }, async (err, data) => {
                if (err) {
                    console.error(err);
                    resolve({ status: false, error: err, data: [], count: 0 })
                }
                let array = []
                let currencyRecord = await this.CurrencyValuationRepo.find()

                for (let index = 1; index < data.length; index++) {
                    const element = data[index];
                    let tempArr = {}
                    for (let jindex = 0; jindex < element.length; jindex++) {
                        const jElement = element[jindex];
                        tempArr[data[0][jindex].replace(/\s+/g, '')] = jElement
                    }
                    if (ReportTYPE == recordTypeEnum.SALES) {
                        // @ts-ignore
                        if (tempArr?.CustomerPrice && tempArr?.CustomerCurrency.toLowerCase() == "usd" && tempArr?.CustomerPrice != "0.00") {
                            //@ts-ignore
                            let result = await this.analyticsService.doStoreICon(tempArr?.AppAppleID)
                            // // @ts-ignore
                            // let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: Number(tempArr?.CustomerPrice), type: ReportTYPE };

                            // if (!!appleVendor == true) {
                            //     obj.AccountID = appleVendor._id
                            // }

                            // if (result && result.data) {
                            //     obj.iconurl = result.data;
                            // }

                            // array.push(obj);
                            // second way to save data 
                            if (result && result?.data) {
                                // @ts-ignore
                                let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: Number(tempArr?.CustomerPrice), type: ReportTYPE, iconurl: result.data }
                                if (!!appleVendor == true) {
                                    obj.AccountID = appleVendor._id
                                }
                                array.push(obj)

                            } else {
                                // @ts-ignore
                                let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: Number(tempArr?.CustomerPrice), type: ReportTYPE }
                                if (!!appleVendor == true) {
                                    obj.AccountID = appleVendor._id
                                }
                                array.push(obj)
                            }

                            // first way to save data 
                            // @ts-ignore
                            // let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: Number(tempArr?.CustomerPrice), type: ReportTYPE, iconurl: result.data }
                            // if (!!appleVendor == true) {
                            //     obj.AccountID = appleVendor._id
                            // }
                            // array.push(obj)
                        }
                        // @ts-ignore
                        if (tempArr?.CustomerPrice && tempArr?.CustomerPrice != "0.00" && tempArr?.CustomerPrice != "0.0" && tempArr?.CustomerCurrency.toLowerCase() !== "usd") {
                            // @ts-ignore
                            // this.doGetUSDBaseValue(tempArr?.ProceedsCurrency, Number(tempArr?.DeveloperProceeds)).then((amount) => {
                            //     // @ts-ignore
                            //     if (amount.status == true) {
                            //         // @ts-ignore
                            //         let obj:AnalyticsReport={ ...tempArr,Units:Number(tempArr?.Units), EventDate: hitDate, DeveloperProceedsInUsd: amount?.value.toFixed(2), type: ReportTYPE }
                            //         if(!!appleVendor==true){
                            //             obj.AccountID=appleVendor._id
                            //         }
                            //         array.push(obj)
                            //     }
                            // })

                            let checkCurrency = currencyRecord.find((i) => i.currency === tempArr?.CustomerCurrency.toLowerCase())

                            if (checkCurrency) {
                                // @ts-ignore
                                let calculateCurrency = tempArr?.CustomerPrice / checkCurrency.rates

                                //@ts-ignore
                                let result = await this.analyticsService.doStoreICon(tempArr?.AppAppleID);
                                // //@ts-ignore
                                // let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: calculateCurrency.toFixed(2), type: ReportTYPE }


                                // if (!!appleVendor == true) {
                                //     obj.AccountID = appleVendor._id
                                // }

                                // if (result && result.data) {
                                //     obj.iconurl = result.data;
                                // }

                                // array.push(obj);

                                // second way to save data 
                                if (result && result?.data) {
                                    //@ts-ignore
                                    let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: calculateCurrency.toFixed(2), type: ReportTYPE, iconurl: result.data }

                                    if (!!appleVendor == true) {
                                        obj.AccountID = appleVendor._id
                                    }
                                    array.push(obj)
                                } else {
                                    //@ts-ignore
                                    let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: calculateCurrency.toFixed(2), type: ReportTYPE }

                                    if (!!appleVendor == true) {
                                        obj.AccountID = appleVendor._id
                                    }
                                    array.push(obj)
                                }

                                // first way to save
                                // //@ts-ignore
                                // let obj: AnalyticsReport = { ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, CustomerProceedsInUsd: calculateCurrency.toFixed(2), type: ReportTYPE, iconurl: result.data }

                                // if (!!appleVendor == true) {
                                //     obj.AccountID = appleVendor._id
                                // }
                                // array.push(obj)
                            }
                        }
                    } else if (ReportTYPE == recordTypeEnum.DOWNLOAD) {
                        //@ts-ignore
                        let result = await this.analyticsService.doStoreICon(tempArr?.AppleIdentifier)

                        // way to save data 
                        if (result && result?.data) {
                            // @ts-ignore
                            array.push({ ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, type: ReportTYPE, AccountID: appleVendor._id, iconurl: result.data })
                        } else {
                            // @ts-ignore
                            array.push({ ...tempArr, Units: Number(tempArr?.Units), EventDate: hitDate, type: ReportTYPE, AccountID: appleVendor._id })
                        }
                    }
                }
                resolve({ status: true, count: array?.length, data: array })
            }
            )
        })
    }
    async doGenerateTokenAPI({ iss, privateKey, keyId }) {
        try {
            return await lastValueFrom(
                this.httpService.post('http://localhost:3000/generate-token', {
                    iss: iss,
                    keyId: keyId,
                    privateKey: privateKey
                }).pipe(
                    map(response => response.data.access_token)
                )
            );
        } catch (error) {
            return {
                status: false,
                data: [],
                message: error.message,
                code: error.status,
                error: error?.response?.data
            }
        }
    }
    async doFetchReports(baseUrl, accountRecord = null) {
        const access_token = await this.doGenerateTokenAPI({
            iss: accountRecord.Issuer, privateKey: accountRecord?.PrivateKey, keyId: accountRecord?.KeyId
        })
        try {
            return await lastValueFrom(
                this.httpService.get(baseUrl, {
                    headers: {
                        'Accept': 'application/a-gzip',
                        'Authorization': `${access_token}`
                    },
                    responseType: 'arraybuffer',
                }).pipe(
                    map(response => {
                        if (response.data) {
                            return {
                                status: true,
                                data: response.data,
                                code: response.status,
                                message: "Data Fetched!"
                            }
                        }
                    })));
        } catch (error) {
            console.log("errror>>>>>>>>>>", baseUrl)
            return {
                status: false,
                data: [],
                message: error.message,
                code: error.response?.status,
                error: error?.response?.data
            }
        }
    }
    generateJWT = async ({ privateKey,
        iss, KeyId }) => {
        const payload = { iss: iss, aud: process.env.audience };

        return {
            access_token: await this.jwtService.sign(payload, {
                header: {
                    alg: process.env.alg,
                    kid: KeyId
                },
                privateKey: privateKey
            })
        };
    }

    doGetReportsUrl(type = null, gDate, appleVendor) {
        if (!type && !gDate) {
            return null
        }
        const date = moment(gDate, this.APPLEDATEFORMAT)
        if (type == recordTypeEnum.DOWNLOAD) {
            return process.env.appleBaseUrl + process.env.salesReport + `?filter[frequency]=DAILY&filter[reportDate]=${date.format(this.APPLEDATEFORMAT)}&filter[reportSubType]=SUMMARY&filter[reportType]=SALES&filter[vendorNumber]=${appleVendor.VendorID}&filter[version]=1_0`
        }
        if (type == recordTypeEnum.SALES) {
            return process.env.appleBaseUrl + process.env.salesReport + `?filter[frequency]=DAILY&filter[reportDate]=${date.format(this.APPLEDATEFORMAT)}&filter[reportSubType]=DETAILED&filter[reportType]=SUBSCRIBER&filter[vendorNumber]=${appleVendor.VendorID}&filter[version]=1_3`
        }
    }

    async convertCurrencyValue(from, to) {
        const url = `https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/${from.toLowerCase()}/${to}.json`
        console.log("URL---", url)
        try {

            return await lastValueFrom(
                this.httpService.get(url).pipe(
                    map(async (response) => {
                        if (response.status == 200) {
                            return { status: true, value: response.data.usd, from, to, date: response.data.date }
                        }
                        else {
                            debugger
                        }
                        if (response.status !== 200) {
                            debugger
                        }
                    }),
                ),
            );
        }
        catch (error) {
            console.log("===============")
            console.log(error)
            console.log("===============")
        }
    }
    enumerateDaysBetweenDates(startDate, endDate) {
        let dates = [];

        // const currDate = moment(startDate, "YYYY-MM-DD");

        // const lastDate = moment(endDate, "YYYY-MM-DD");

        // dates.push(currDate.clone().toDate())

        // console.log("DIFF",currDate.add(1, 'days').diff(lastDate) < 0)
        // while (currDate.add(1, 'days').diff(lastDate) < 0) {
        //     console.log(currDate.toDate());
        //     dates.push(currDate.clone().toDate());
        // }
        // dates.push(lastDate.clone().toDate())   

        const currDate = moment(startDate, "YYYY-MM-DD");
        const lastDate = moment(endDate, "YYYY-MM-DD");

        while (lastDate.diff(currDate) >= 0) {
            dates.push(moment(currDate).format("YYYY-MM-DD"));
            currDate.add(1, 'days');
        }
        return dates;
    };


    doGetUSDBaseValue = async (Currency, amount) => {
        let data = await this.CurrencyValuationRepo.findOne({ currency: Currency }).sort({ "createdAt": -1 }).limit(1).exec();

        if (data) {
            return { value: data.rates * amount, status: true }
        }
        return { value: null, status: false }
    }
}