import { HttpService } from "@nestjs/axios";
import { Injectable, Logger } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import axios from "axios";
import * as moment from "moment";
import mongoose from "mongoose";
import { catchError, lastValueFrom, map } from "rxjs";
import { AnalyticsReport, recordTypeEnum } from "src/models/AnalyticsReport.schema";
import * as fs from 'fs';
import * as zlib from 'zlib'
import { parse } from 'csv-parse'
import { JwtService } from '@nestjs/jwt';
import { CurrencyValuation } from "src/models/CurrencyValuation.schema";
import * as CurrencyConverter from 'currency-converter-lt'
import { AppleAccount } from "src/models/AppleAccount.schema";
import { LoggerService } from "src/utils/logger.service";

@Injectable()
export class AnalyticsReportService {
  CONST_REPORT_TYPES = {
    SALES: 'SALES',
    DOWNLOAD: 'DOWNLOAD'
  }

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

  async dohandleSyncDownloadReports(): Promise<any> {
    try {
      const ReportTYPE = recordTypeEnum.DOWNLOAD
      const hitDate = new Date()
      const baseUrl = await this.doGetReportsUrl(ReportTYPE, hitDate)
      const response = await this.axiosApiCall(baseUrl)
      if (response?.status) {
        const filePath = "public/tempReports/" + 'sr.gz';
        console.log(__dirname)
        fs.writeFileSync(filePath, response?.data);
        const decompressedData = await zlib.gunzipSync(response.data);
        const decompressedString = decompressedData.toString('utf-8');
        const resolve = await new Promise((resolve, reject) => {
          parse(decompressedString, { delimiter: '\t' }, (err, data) => {
            if (err) {
              console.error(err);
              resolve({ status: false, error: err })
            } else {
              let array = []
              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
                }
                array.push({ ...tempArr, EventDate: hitDate, type: ReportTYPE })
              }
              this.analyticsReportRepo.insertMany(array)
              resolve({ status: true, count: data?.length - 1, data: array })
            }
          });
        })
        // @ts-ignore
        if (resolve?.status == true) {
          return resolve
        }
      }
      if (response?.status == false) {
        if (response.error.response.status == 401) {
          return {
            status: false,
            code: response.error.response.status
          }
        }
      }
    }
    catch (error) {
      console.log(error)
      if (error.response.status == 401) {
        return {
          status: false,
          code: error.response.status
        }
      }
    }

  }

  async doGetVendorList() {
    let vendorRecord = await this.appleAccountRepo.find().select({
      _id: 1,
      VendorID: 1,
      AccountName: 1
    })

    if (!vendorRecord) {
      return {
        code: 404,
        status: 'Vendor Not Found'
      }
    }
    return {
      data: vendorRecord,
      status: true
    }
  }

  async dohandleSyncSalesReports(): Promise<any> {
    try {
      const ReportTYPE = recordTypeEnum.SALES
      // const hitDate=moment().set({
      //   day:7
      // })
      // const hitDate=moment("2024-01-02","YYYY-MM-DD")
      const hitDate = moment()
      const baseUrl = await this.doGetReportsUrl(ReportTYPE, hitDate.format("YYYY-MM-DD"))
      const response = await this.axiosApiCall(baseUrl)
      if (response?.status) {
        const filePath = "public/tempReports/" + 'sr.gz';
        console.log(__dirname)
        fs.writeFileSync(filePath, response?.data);
        const decompressedData = await zlib.gunzipSync(response.data);
        const decompressedString = decompressedData.toString('utf-8');
        const resolve = await new Promise((resolve, reject) => {
          parse(decompressedString, { delimiter: '\t' }, async (err, data) => {
            if (err) {
              console.error(err);
              resolve({ status: false, error: err })
            } else {
              let array = []
              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
                }
                // @ts-ignore
                if (tempArr?.DeveloperProceeds && tempArr?.ProceedsCurrency.toLowerCase() == "usd") {
                  // @ts-ignore
                  array.push({ ...tempArr, EventDate: hitDate.toDate(), DeveloperProceedsInUsd: Number(tempArr?.DeveloperProceeds), type: ReportTYPE })
                }
                // @ts-ignore
                if (tempArr?.DeveloperProceeds && tempArr?.DeveloperProceeds != "0.00" && tempArr?.DeveloperProceeds != "0.0" && tempArr?.ProceedsCurrency.toLowerCase() !== "usd") {
                  // @ts-ignore
                  const amount = await this.doGetUSDBaseValue(tempArr?.ProceedsCurrency, Number(tempArr?.DeveloperProceeds))
                  // @ts-ignore
                  if (amount.status == true) {
                    // @ts-ignore
                    array.push({ ...tempArr, EventDate: hitDate.toDate(), DeveloperProceedsInUsd: amount?.value.toFixed(2), type: ReportTYPE })
                  }
                  else {
                    debugger
                  }
                }
              }
              this.analyticsReportRepo.insertMany(array)
              resolve({ status: true, count: data?.length - 1, data: array })
            }
          });
        })
        // @ts-ignore
        if (resolve?.status == true) {
          return resolve
        }
      }
      if (response?.status == false) {
        if (response.error.response.status == 401) {
          return {
            status: false,
            code: response.error.response.status
          }
        }
      }
    }
    catch (error) {
      console.log(error)
      if (error.response.status == 401) {
        return {
          status: false,
          code: error.response.status
        }
      }
    }
  }
  doGetReportsUrl(type = null, gDate) {
    if (!type && !gDate) {
      return null
    }
    const date = moment(gDate, "YYYY-MM-DD")
    if (date.format("DD-MM-YYYY") == moment().format("DD-MM-YYYY")) {
      date.add(-3, 'days')
    }
    if (type == recordTypeEnum.DOWNLOAD) {
      return process.env.appleBaseUrl + process.env.salesReport + `?filter[frequency]=DAILY&filter[reportDate]=${date.format("YYYY-MM-DD")}&filter[reportSubType]=SUMMARY&filter[reportType]=SALES&filter[vendorNumber]=88511218&filter[version]=1_0`
    }
    if (type == recordTypeEnum.SALES) {
      return process.env.appleBaseUrl + process.env.salesReport + `?filter[frequency]=DAILY&filter[reportDate]=${date.format("YYYY-MM-DD")}&filter[reportSubType]=DETAILED&filter[reportType]=SUBSCRIBER&filter[vendorNumber]=88511218&filter[version]=1_3`
    }
  }
  async axiosApiCall(baseUrl) {
    try {
      const { access_token } = await this.generateJWT()
      const response = await axios.get(baseUrl, {
        headers: {
          'Accept': 'application/a-gzip',
          'Authorization': `Bearer ${access_token}`
        },
        responseType: 'arraybuffer',
      })
      if (response.data) {
        return {
          status: true,
          data: response.data
        }
      }
    }
    catch (error) {
      return {
        status: false,
        data: [],
        error: error
      }
    }
  }

  generateJWT = async () => {
    // 'https://api.appstoreconnect.apple.com/v1/salesReports?filter[frequency]=DAILY&filter[reportDate]=2024-05-21&filter[reportSubType]=DETAILED&filter[reportType]=SUBSCRIBER&filter[vendorNumber]=86004796&filter[version]=1_3'

    const payload = { iss: "0151c562-d58a-490f-a7f0-f5d18116d0c5", aud: 'appstoreconnect-v1' };
    return {
      access_token: await this.jwtService.sign(payload, {
        header: {
          alg: 'ES256',
          kid: 'V7Q3223B7F'
        }

      })
    };
  }
  doHandleParsingCSV = async () => {
    // https://gist.github.com/HarishChaudhari/4680482
    const csvCountry = `Country,CountryCode,Currency,Code
    New Zealand,NZ,New Zealand Dollars,NZD
    Cook Islands,CK,New Zealand Dollars,NZD
    Niue,NU,New Zealand Dollars,NZD
    Pitcairn,PN,New Zealand Dollars,NZD
    Tokelau,TK,New Zealand Dollars,NZD
    Australian,AU,Australian Dollars,AUD
    Christmas Island,CX,Australian Dollars,AUD
    Cocos (Keeling) Islands,CC,Australian Dollars,AUD
    Heard and Mc Donald Islands,HM,Australian Dollars,AUD
    Kiribati,KI,Australian Dollars,AUD
    Nauru,NR,Australian Dollars,AUD
    Norfolk Island,NF,Australian Dollars,AUD
    Tuvalu,TV,Australian Dollars,AUD
    American Samoa,AS,Euros,EUR
    Andorra,AD,Euros,EUR
    Austria,AT,Euros,EUR
    Belgium,BE,Euros,EUR
    Finland,FI,Euros,EUR
    France,FR,Euros,EUR
    French Guiana,GF,Euros,EUR
    French Southern Territories,TF,Euros,EUR
    Germany,DE,Euros,EUR
    Greece,GR,Euros,EUR
    Guadeloupe,GP,Euros,EUR
    Ireland,IE,Euros,EUR
    Italy,IT,Euros,EUR
    Luxembourg,LU,Euros,EUR
    Martinique,MQ,Euros,EUR
    Mayotte,YT,Euros,EUR
    Monaco,MC,Euros,EUR
    Netherlands,NL,Euros,EUR
    Portugal,PT,Euros,EUR
    Reunion,RE,Euros,EUR
    Samoa,WS,Euros,EUR
    San Marino,SM,Euros,EUR
    Slovenia,SI,Euros,EUR
    Spain,ES,Euros,EUR
    Vatican City State (Holy See),VA,Euros,EUR
    South Georgia and the South Sandwich Islands,GS,Sterling,GBP
    United Kingdom,GB,Sterling,GBP
    Jersey,JE,Sterling,GBP
    British Indian Ocean Territory,IO,USD,USD
    Guam,GU,USD,USD
    Marshall Islands,MH,USD,USD
    Micronesia Federated States of,FM,USD,USD
    Northern Mariana Islands,MP,USD,USD
    Palau,PW,USD,USD
    Puerto Rico,PR,USD,USD
    Turks and Caicos Islands,TC,USD,USD
    United States,US,USD,USD
    United States Minor Outlying Islands,UM,USD,USD
    Virgin Islands (British),VG,USD,USD
    Virgin Islands (US),VI,USD,USD
    Hong Kong,HK,HKD,HKD
    Canada,CA,Canadian Dollar,CAD
    Japan,JP,Japanese Yen,JPY
    Afghanistan,AF,Afghani,AFN
    Albania,AL,Lek,ALL
    Algeria,DZ,Algerian Dinar,DZD
    Anguilla,AI,East Caribbean Dollar,XCD
    Antigua and Barbuda,AG,East Caribbean Dollar,XCD
    Dominica,DM,East Caribbean Dollar,XCD
    Grenada,GD,East Caribbean Dollar,XCD
    Montserrat,MS,East Caribbean Dollar,XCD
    Saint Kitts,KN,East Caribbean Dollar,XCD
    Saint Lucia,LC,East Caribbean Dollar,XCD
    Saint Vincent Grenadines,VC,East Caribbean Dollar,XCD
    Argentina,AR,Peso,ARS
    Armenia,AM,Dram,AMD
    Aruba,AW,Netherlands Antilles Guilder,ANG
    Netherlands Antilles,AN,Netherlands Antilles Guilder,ANG
    Azerbaijan,AZ,Manat,AZN
    Bahamas,BS,Bahamian Dollar,BSD
    Bahrain,BH,Bahraini Dinar,BHD
    Bangladesh,BD,Taka,BDT
    Barbados,BB,Barbadian Dollar,BBD
    Belarus,BY,Belarus Ruble,BYR
    Belize,BZ,Belizean Dollar,BZD
    Benin,BJ,CFA Franc BCEAO,XOF
    Burkina Faso,BF,CFA Franc BCEAO,XOF
    Guinea-Bissau,GW,CFA Franc BCEAO,XOF
    Ivory Coast,CI,CFA Franc BCEAO,XOF
    Mali,ML,CFA Franc BCEAO,XOF
    Niger,NE,CFA Franc BCEAO,XOF
    Senegal,SN,CFA Franc BCEAO,XOF
    Togo,TG,CFA Franc BCEAO,XOF
    Bermuda,BM,Bermudian Dollar,BMD
    Bhutan,BT,Indian Rupee,INR
    India,IN,Indian Rupee,INR
    Bolivia,BO,Boliviano,BOB
    Botswana,BW,Pula,BWP
    Bouvet Island,BV,Norwegian Krone,NOK
    Norway,NO,Norwegian Krone,NOK
    Svalbard and Jan Mayen Islands,SJ,Norwegian Krone,NOK
    Brazil,BR,Brazil,BRL
    Brunei Darussalam,BN,Bruneian Dollar,BND
    Bulgaria,BG,Lev,BGN
    Burundi,BI,Burundi Franc,BIF
    Cambodia,KH,Riel,KHR
    Cameroon,CM,CFA Franc BEAC,XAF
    Central African Republic,CF,CFA Franc BEAC,XAF
    Chad,TD,CFA Franc BEAC,XAF
    Congo Republic of the Democratic,CG,CFA Franc BEAC,XAF
    Equatorial Guinea,GQ,CFA Franc BEAC,XAF
    Gabon,GA,CFA Franc BEAC,XAF
    Cape Verde,CV,Escudo,CVE
    Cayman Islands,KY,Caymanian Dollar,KYD
    Chile,CL,Chilean Peso,CLP
    China,CN,Yuan Renminbi,CNY
    Colombia,CO,Peso,COP
    Comoros,KM,Comoran Franc,KMF
    Congo-Brazzaville,CD,Congolese Frank,CDF
    Costa Rica,CR,Costa Rican Colon,CRC
    Croatia (Hrvatska),HR,Croatian Dinar,HRK
    Cuba,CU,Cuban Peso,CUP
    Cyprus,CY,Cypriot Pound,CYP
    Czech Republic,CZ,Koruna,CZK
    Denmark,DK,Danish Krone,DKK
    Faroe Islands,FO,Danish Krone,DKK
    Greenland,GL,Danish Krone,DKK
    Djibouti,DJ,Djiboutian Franc,DJF
    Dominican Republic,DO,Dominican Peso,DOP
    East Timor,TP,Indonesian Rupiah,IDR
    Indonesia,ID,Indonesian Rupiah,IDR
    Ecuador,EC,Sucre,ECS
    Egypt,EG,Egyptian Pound,EGP
    El Salvador,SV,Salvadoran Colon,SVC
    Eritrea,ER,Ethiopian Birr,ETB
    Ethiopia,ET,Ethiopian Birr,ETB
    Estonia,EE,Estonian Kroon,EEK
    Falkland Islands (Malvinas),FK,Falkland Pound,FKP
    Fiji,FJ,Fijian Dollar,FJD
    French Polynesia,PF,CFP Franc,XPF
    New Caledonia,NC,CFP Franc,XPF
    Wallis and Futuna Islands,WF,CFP Franc,XPF
    Gambia,GM,Dalasi,GMD
    Georgia,GE,Lari,GEL
    Gibraltar,GI,Gibraltar Pound,GIP
    Guatemala,GT,Quetzal,GTQ
    Guinea,GN,Guinean Franc,GNF
    Guyana,GY,Guyanaese Dollar,GYD
    Haiti,HT,Gourde,HTG
    Honduras,HN,Lempira,HNL
    Hungary,HU,Forint,HUF
    Iceland,IS,Icelandic Krona,ISK
    Iran (Islamic Republic of),IR,Iranian Rial,IRR
    Iraq,IQ,Iraqi Dinar,IQD
    Israel,IL,Shekel,ILS
    Jamaica,JM,Jamaican Dollar,JMD
    Jordan,JO,Jordanian Dinar,JOD
    Kazakhstan,KZ,Tenge,KZT
    Kenya,KE,Kenyan Shilling,KES
    Korea North,KP,Won,KPW
    Korea South,KR,Won,KRW
    Kuwait,KW,Kuwaiti Dinar,KWD
    Kyrgyzstan,KG,Som,KGS
    Lao PeopleÕs Democratic Republic,LA,Kip,LAK
    Latvia,LV,Lat,LVL
    Lebanon,LB,Lebanese Pound,LBP
    Lesotho,LS,Loti,LSL
    Liberia,LR,Liberian Dollar,LRD
    Libyan Arab Jamahiriya,LY,Libyan Dinar,LYD
    Liechtenstein,LI,Swiss Franc,CHF
    Switzerland,CH,Swiss Franc,CHF
    Lithuania,LT,Lita,LTL
    Macau,MO,Pataca,MOP
    Macedonia,MK,Denar,MKD
    Madagascar,MG,Malagasy Franc,MGA
    Malawi,MW,Malawian Kwacha,MWK
    Malaysia,MY,Ringgit,MYR
    Maldives,MV,Rufiyaa,MVR
    Malta,MT,Maltese Lira,MTL
    Mauritania,MR,Ouguiya,MRO
    Mauritius,MU,Mauritian Rupee,MUR
    Mexico,MX,Peso,MXN
    Moldova Republic of,MD,Leu,MDL
    Mongolia,MN,Tugrik,MNT
    Morocco,MA,Dirham,MAD
    Western Sahara,EH,Dirham,MAD
    Mozambique,MZ,Metical,MZN
    Myanmar,MM,Kyat,MMK
    Namibia,NA,Dollar,NAD
    Nepal,NP,Nepalese Rupee,NPR
    Nicaragua,NI,Cordoba Oro,NIO
    Nigeria,NG,Naira,NGN
    Oman,OM,Sul Rial,OMR
    Pakistan,PK,Rupee,PKR
    Panama,PA,Balboa,PAB
    Papua New Guinea,PG,Kina,PGK
    Paraguay,PY,Guarani,PYG
    Peru,PE,Nuevo Sol,PEN
    Philippines,PH,Peso,PHP
    Poland,PL,Zloty,PLN
    Qatar,QA,Rial,QAR
    Romania,RO,Leu,RON
    Russian Federation,RU,Ruble,RUB
    Rwanda,RW,Rwanda Franc,RWF
    Sao Tome and Principe,ST,Dobra,STD
    Saudi Arabia,SA,Riyal,SAR
    Seychelles,SC,Rupee,SCR
    Sierra Leone,SL,Leone,SLL
    Singapore,SG,Dollar,SGD
    Slovakia (Slovak Republic),SK,Koruna,SKK
    Solomon Islands,SB,Solomon Islands Dollar,SBD
    Somalia,SO,Shilling,SOS
    South Africa,ZA,Rand,ZAR
    Sri Lanka,LK,Rupee,LKR
    Sudan,SD,Dinar,SDG
    Suriname,SR,Surinamese Guilder,SRD
    Swaziland,SZ,Lilangeni,SZL
    Sweden,SE,Krona,SEK
    Syrian Arab Republic,SY,Syrian Pound,SYP
    Taiwan,TW,Dollar,TWD
    Tajikistan,TJ,Tajikistan Ruble,TJS
    Tanzania,TZ,Shilling,TZS
    Thailand,TH,Baht,THB
    Tonga,TO,PaÕanga,TOP
    Trinidad and Tobago,TT,Trinidad and Tobago Dollar,TTD
    Tunisia,TN,Tunisian Dinar,TND
    Turkey,TR,Lira,TRY
    Turkmenistan,TM,Manat,TMT
    Uganda,UG,Shilling,UGX
    Ukraine,UA,Hryvnia,UAH
    United Arab Emirates,AE,Dirham,AED
    Uruguay,UY,Peso,UYU
    Uzbekistan,UZ,Som,UZS
    Vanuatu,VU,Vatu,VUV
    Venezuela,VE,Bolivar,VEF
    Vietnam,VN,Dong,VND
    Yemen,YE,Rial,YER
    Zambia,ZM,Kwacha,ZMK
    Zimbabwe,ZW,Zimbabwe Dollar,ZWD
    Aland Islands,AX,Euro,EUR
    Angola,AO,Angolan kwanza,AOA
    Antarctica,AQ,Antarctican dollar,AQD
    Bosnia and Herzegovina,BA,Bosnia and Herzegovina convertible mark,BAM
    Congo (Kinshasa),CD,Congolese Frank,CDF
    Ghana,GH,Ghana cedi,GHS
    Guernsey,GG,Guernsey pound,GGP
    Isle of Man,IM,Manx pound,GBP
    Laos,LA,Lao kip,LAK
    Macao S.A.R.,MO,Macanese pataca,MOP
    Montenegro,ME,Euro,EUR
    Palestinian Territory,PS,Jordanian dinar,JOD
    Saint Barthelemy,BL,Euro,EUR
    Saint Helena,SH,Saint Helena pound,GBP
    Saint Martin (French part),MF,Netherlands Antillean guilder,ANG
    Saint Pierre and Miquelon,PM,Euro,EUR
    Serbia,RS,Serbian dinar,RSD
    US Armed Forces,USAF,US Dollar,USD`
    const response = await new Promise((resolve, reject) => {
      parse(csvCountry, { delimiter: ',' }, (err, data) => {
        if (err) {
          console.error(err);
          resolve({ status: false, error: err })
        } else {
          let array = []
          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].trim();
              tempArr[data[0][jindex].replace(/\s+/g, '')] = jElement
            }
            array.push({ ...tempArr })
          }
          resolve({ status: true, count: data?.length - 1, data: array })
        }
      });

    })
    // @ts-ignore
    if (response?.status == true) {
      return response
    }
  }
  doSyncCurrency = async (syncingDate = null) => {
    return await this.doGetCurrentConvertedCurrencyValue("CAD", "USD", 10.62)
    return
    const date = moment(syncingDate, "DD-MM-YYYY")
    if (!date.isValid()) {
      return {
        status: false,
        message: "Invalid Date",
        code: 422
      }
    }
    const endpoint = process.env.exchangeRateBaseUrl1 + date.format("YYYY-MM-DD") + "?access_key=" + process.env.exchangeRateAccessKey1
    const responseData = await lastValueFrom(
      this.httpService.get(endpoint).pipe(
        map(async (response) => {
          if (response.status == 200) {
            const data = response.data
            await this.CurrencyValuationRepo.create({
              currencyBase: data.base,
              rates: data.rates,
              syncDate: date.toDate(),
              createdAt: new Date(),
            })
          }
          return { status: true };
        }),
      ),
    );
    console.log(responseData)
    return JSON.stringify(responseData)
  }

  doGetAnalyticsForDate = async (from, to, type, AccountID) => {
    // let { from, to, type, AccountID } = payload;

    const mongooseAccountIds = AccountID.map(id => new mongoose.Types.ObjectId(id));
    const diffDays = (date, otherDate) => Math.ceil(Math.abs(date - otherDate) / (1000 * 60 * 60 * 24));

    let fromDateFormatted = moment(from, 'DD-MM-YYYY').startOf('day').toDate();
    let toDateFormatted = moment(to, 'DD-MM-YYYY').endOf('day').toDate();
    const fromDate = moment(from, "DD-MM-YYYY").set({
      hour: 0,
      minute: 0,
      second: 0
    })
    const toDate = moment(to, "DD-MM-YYYY").set({
      hour: 11,
      minute: 59,
      second: 59
    })
    // let dateRecord = await this.analyticsReportRepo.aggregate([
    //   {
    //     $match: {
    //       EventDate: {
    //         $gte: fromDateFormatted,
    //         $lte: toDateFormatted,
    //       },
    //       AccountID: { $in: mongooseAccountIds },
    //     }
    //   },
    //   {
    //     $lookup: {
    //       from: 'appleaccounts',
    //       localField: 'AccountID',
    //       foreignField: '_id',
    //       as: 'matchedData'
    //     }
    //   }
    //   // {
    //   //   $lookup: {
    //   //     from: 'AppleAccount',
    //   //     let: { accountId: { $toObjectId: '$AccountID' } },
    //   //     pipeline: [
    //   //       {
    //   //         $match: {
    //   //           $expr: { $eq: ['$_id', '$$accountId'] }
    //   //         }
    //   //       }
    //   //     ],
    //   //     as: 'matchedData'
    //   //   }
    //   // }
    // ])

    // if (!dateRecord || dateRecord.length === 0) {
    //   return {
    //     // data: {
    //     message: "data not sync",
    //     data: [],
    //     code: 404
    //     // }
    //   }
    // }

    const RecordKeyType = type.toUpperCase() == "SALES" ? "TotalSales" : "TotalDownloads"
    const dateCount = diffDays(fromDate.toDate(), toDate.toDate())
    const prevFromDate = moment(from, "DD-MM-YYYY").subtract(dateCount, "days")
    const prevToDate = moment(fromDate).subtract(1, "days")

    const doGetAggregateRecords = async (fromDate, toDate, ProductTypeIdentifier = null, AppNameKey, SummationKey) => await this.analyticsReportRepo.aggregate([
      {
        $match: {
          EventDate: {
            $gte: new Date(new Date(fromDate).setHours(0, 0, 0, 0)),
            $lte: new Date(new Date(toDate).setHours(23, 59, 59, 999)),
          },
          type: type.toUpperCase(),
          AccountID: { $in: mongooseAccountIds },
          ProductTypeIdentifier: ProductTypeIdentifier
        },
      },
      {
        // 👇 Lookup account name from "accounts" collection
        $lookup: {
          from: "appleaccounts",
          localField: "AccountID",
          foreignField: "_id",
          as: "accountData"
        }
      },
      {
        $unwind: "$accountData"
      },
      {
        "$group": {
          "_id": {
            "date": {
              "$dateToString": {
                // "format": "%Y-%m-%d",
                "format": "%d-%b-%Y",
                "date": "$EventDate"
              }
            },
            AppName: AppNameKey,
            iconurl: "$iconurl",
            AccountName: "$accountData.AccountName"
          },
          [RecordKeyType]: {
            "$sum": SummationKey
          }
        }
      },
      {
        $sort: { "_id.date": 1 }
      },
      {
        "$group": {
          "_id": "$_id.AppName",
          "AppName": { $first: "$_id.AppName" },
          "AccountName": { $first: "$_id.AccountName" },
          "iconurl": { $first: "$_id.iconurl" },
          "breakup": {
            "$push": {
              "EventDate": "$_id.date",
              "AppName": "$_id.AppName",
              // [RecordKeyType]: `$${RecordKeyType}`
              [RecordKeyType]: {
                $round: [`$${RecordKeyType}`, 2]
              }
            }
          },
        }
      },
      {
        $sort: { "_id": 1 }
      },
    ])
    const APPNAMEKEY = type.toUpperCase() == "SALES" ? "$AppName" : "$Title"
    // const SUMMATIONKEY = type.toUpperCase() == "SALES" ? "$DeveloperProceedsInUsd" : "$Units"
    const SUMMATIONKEY = type.toUpperCase() == "SALES" ? "$CustomerProceedsInUsd" : "$Units"
    const PRODUCTTYPEIDENTIFIERKEY = type.toUpperCase() == "SALES" ? null : "1F"
    const currentRangeRecord = await doGetAggregateRecords(fromDate.toDate(), toDate.toDate(), PRODUCTTYPEIDENTIFIERKEY, APPNAMEKEY, SUMMATIONKEY);
    const previousRangeRecord = await doGetAggregateRecords(prevFromDate.toDate(), prevToDate.toDate(), PRODUCTTYPEIDENTIFIERKEY, APPNAMEKEY, SUMMATIONKEY);

    let currData = currentRangeRecord;
    let totalCurrentData = 0
    let totalPreviousData = 0
    if (!!currData?.length == true || !!previousRangeRecord?.length == true) {
      for (let i = 0; i < currData.length; i++) {
        let currentGrandTotal = 0;
        let previousGrandTotal = 0;
        for (let j = 0; j < currData[i].breakup.length; j++) {
          currentGrandTotal += currData[i].breakup[j][RecordKeyType] ? currData[i].breakup[j][RecordKeyType] : 0
          // if (currData[i]?.breakup[j]?.AppName == previousRangeRecord[i]?.breakup[j]?.AppName) {
          //   console.log("MATCHED___________", currData[i]?.breakup[j].AppName);
          //   currData[i].breakup[j]["Prev" + RecordKeyType] = previousRangeRecord[i].breakup[j][RecordKeyType];
          //   currData[i].breakup[j]["PrevEventDate"] = previousRangeRecord[i].breakup[j]?.EventDate;
          // } else {
          //   console.log("NOT MATCHED___________", currData[i]?.breakup[j].AppName);
          //   console.log("_____LOOPING");
          //   for (let k = 0; k < previousRangeRecord?.length; k++) {
          //     for (let l = 0; l < previousRangeRecord[k].breakup.length; l++) {
          //       if (currData[i]?.breakup[j]?.AppName == previousRangeRecord[k].breakup[j]?.AppName) {
          //         console.log("LOOPED_MATCHED");
          //         currData[i].breakup[j]["Prev" + RecordKeyType] = previousRangeRecord[k].breakup[j][RecordKeyType];
          //         currData[i].breakup[j]["PrevEventDate"] = previousRangeRecord[k]?.breakup[j]?.EventDate;
          //       }
          //     }
          //   }
          // }
          // previousGrandTotal += currData[i].breakup[j]["Prev" + RecordKeyType] ? currData[i].breakup[j]["Prev" + RecordKeyType] : 0
        }
        let prevData = previousRangeRecord.filter((e) => e._id == currData[i]._id)

        previousGrandTotal = prevData.length > 0 ? prevData[0].breakup.reduce((accumulator, item) => {
          let incValue = item.TotalSales ? item.TotalSales : item.TotalDownloads
          return !incValue ? accumulator : accumulator += incValue
        }, 0) : 0

        currData[i].currentGrandTotal = currentGrandTotal;
        currData[i].previousGrandTotal = previousGrandTotal;
        totalCurrentData += currentGrandTotal;
        totalPreviousData += previousGrandTotal
      }
    }

    // this.loggerService.log(`Retrive report processed successfully: ${currData}`);

    return {
      // data: {
      currentData: currData,
      currTotal: totalCurrentData.toFixed(2),
      prevTotal: totalPreviousData.toFixed(2),
      // },
      status: true
    }
  }

  analysticsData = async (from, to, recordTypeEnum, AccountID) => {
    try {
      let data = []
      let downloadData = []

      const apiPath = '/analytics';

      // this.loggerService.logApiCall('Sales Analytics API');
      data.push(await this.doGetAnalyticsForDate(from, to, recordTypeEnum.SALES, AccountID))

      // this.loggerService.log(`Sync report processed successfully for record: ${data}`);
      // this.loggerService.logApiCall('Download Analytics API');
      downloadData.push(await this.doGetAnalyticsForDate(from, to, recordTypeEnum.DOWNLOAD, AccountID))
      // this.loggerService.log(`Sync report processed successfully for record: ${downloadData}`);

      // Log each object in data array
      data.forEach(item => {
        this.loggerService.log(`Retieve report  successfully for salesRecord` + `${JSON.stringify(item)}`);
      });

      // Log each object in downloadData array
      downloadData.forEach(item => {
        this.loggerService.log(`Retieve report successfully for downloadRecord` + ` ${JSON.stringify(item)}`);
      });


      // for (let i = 0; i < data.length; i++) {
      //   for (let j = 0; j < data[i].currentData.length; j++) {
      //     // console.log(data[i].currentData[j].AppName, 'saleMatch>>>>>>>');
      //     for (let k = 0; k < downloadData.length; k++) {
      //       for (let l = 0; l < downloadData[k].currentData.length; l++) {
      //         // console.log(downloadData[k].currentData[l].AppName, 'download match>>>>>>>')
      //         if (data[i].currentData[j].AppName === downloadData[k].currentData[l].AppName) {
      //           console.log(data[i].currentData[j].AppName, 'ifffsaleMatch>>>>>>>');
      //           console.log(downloadData[k].currentData[l].AppName, 'iffffdownload match>>>>>>>')
      //           console.log("same appName");
      //           for (let index = 0; index < data[i].currentData[j].breakup.length; index++) {
      //             console.log(data[i].currentData[j].breakup[index]);
      //             for (let jndex = 0; jndex < downloadData[k].currentData[l].breakup.length; jndex++) {
      //               console.log(downloadData[k].currentData[l].breakup[jndex]);
      //               if (data[i].currentData[j].breakup[index].EventDate == downloadData[k].currentData[l].breakup[jndex].EventDate) {
      //                 console.log("same date");
      //                 data[i].currentData[j].breakup[index].TotalDownloads = downloadData[k].currentData[l].breakup[jndex].TotalDownloads;
      //                 data[i].currentData[j].breakup[index].PrevTotalDownloads = downloadData[k].currentData[l].breakup[jndex].PrevTotalDownloads;
      //               }
      //             }
      //           }
      //         } else {
      //           console.log('not match>>>>>>');
      //         }
      //       }
      //     }
      //   }
      // }
      return { data, downloadData }
    } catch (e) {
      this.loggerService.log('error>>>>>');
      this.loggerService.log('retrieve api failed....' + `${JSON.stringify(e)}`)
    }
  }

  doSyncCurrencyInRange = (from = "", to = "") => {
    if (from == "" || to == "") {
      return false
    }

  }
  doGetUSDBaseValue = async (currency, amount) => {
    const data = await this.CurrencyValuationRepo.findOne({ currency: currency.toUpperCase() }).sort({ "createdAt": -1 }).limit(1)
    if (data) {
      return { value: data.rates * amount, status: true }
    }
    return { value: null, status: false }

  }
  doGetCurrentConvertedCurrencyValue = async (from, to, amount) => {
    return await new Promise((resolve, reject) => {
      let currencyConverterClass = new CurrencyConverter({ from, to, amount })
      currencyConverterClass.convert().then((response) => {
        resolve({ status: true, value: response })
      }).catch(error => {
        resolve({
          status: false,
          value: null
        })
      })
    })
  }

  async mergeAnalyticsData(from, to, AccountID) {

    const mongooseAccountIds = AccountID.map(id => new mongoose.Types.ObjectId(id));

    let fromDateFormatted = moment(from, 'DD-MM-YYYY').startOf('day').toDate();

    let toDateFormatted = moment(to, 'DD-MM-YYYY').endOf('day').toDate();

    const fromDate = moment(from, "DD-MM-YYYY").set({
      hour: 0,
      minute: 0,
      second: 0
    })

    const toDate = moment(to, "DD-MM-YYYY").set({
      hour: 11,
      minute: 59,
      second: 59
    })

    let record = await this.analyticsReportRepo.aggregate([
      {
        $match: {
          EventDate: {
            $gte: fromDateFormatted,
            $lte: toDateFormatted,
          },
          AccountID: { $in: mongooseAccountIds },
        },
      },
      // {
      //   $group: {
      //     _id: "$type",
      //     data: { $push: "$$ROOT" }
      //   }
      // },
      // {
      //   $project: {
      //     _id: 0,
      //     type: "$_id",
      //     data: {
      //       $map: {
      //         input: "$data",
      //         as: "item",
      //         in: {
      //           _id: "$$item._id",
      //           EventDate: "$$item.EventDate",
      //           type: "$$item.type",
      //           AppName: "$$item.AppName",
      //           Title: "$$item.Title",
      //           CustomerProceedsInUsd: "$$item.CustomerProceedsInUsd",
      //           Unit: "$$item.Units",

      //         }
      //       }
      //     }
      //   }
      // }
      {
        $group: {
          _id: "$type",
          type: { $first: "$type" }, // Store the 'type' field in the 'type' key
          data: {
            $push: {
              _id: "$_id",
              EventDate: "$EventDate",
              AppName: "$AppName",
              type: "$type",
              Title: "$Title",
              CustomerProceedsInUsd: "$CustomerProceedsInUsd",
              Units: "$Units",
              ProductTypeIdentifier: "$ProductTypeIdentifier",
              iconUrl: "$iconurl"
            }
          }
        }
      },
      {
        $project: {
          _id: 0,
          type: 1,
          data: 1
        }
      }
    ])

    for (let i = 0; i < record.length; i++) {
      const element = record[i];
      console.log(element, 'elel');
    }
    return record;
  }


  async doStoreICon(payload) {
    try {
      const url = `https://itunes.apple.com/lookup?id=${payload}`

      return await lastValueFrom(
        this.httpService.get(url).pipe(
          map(async (response) => {
            if (response.status == 200) {
              for (let i = 0; i < response.data.results.length; i++) {
                if (response.data.results.length === 0) {
                  return { status: false, data: [] }
                } else {
                  let result = response.data.results[i]?.artworkUrl60
                  return { status: true, data: result }
                }
              }
            }
          }),
        ),
      );
    }
    catch (error) {
      console.log(error, 'error>>>>>>>>')
    }
  }
}
