import { guidRegex, Utility, Timeouts, dateFormatPattern } from '@utility-lib/index';
import { localizationData } from '@fixtures/commerce/localization_data';
import { FlightUtility } from '@flight-modal/flight_utility';
import { FlightItinerary } from '@flight-lib/itinerary';
import { xmlEu } from '@fixtures/commerce/xml/xml_eu';
import { CommerceShared } from '@commerce-lib/shared';
import { StripeValidation } from '@commerce-lib/stripe/stripe_validation';

const english = localizationData.english;
const adminCreds = Cypress.env('newUser').NEW_USER_PASSWORD;
const xmldata = xmlEu.xmlDataFlight;
const cacheKey = xmldata.cacheKey;
const bookingID = english.bookingID;
const tdsIndia = localizationData.india_Tds;
const flightVoid = localizationData.flight.flight_void;
const flightRefund = localizationData.flight.flight_refund;
const flightExchange = localizationData.flight.flight_exchange;
const flightAncilliaries = localizationData.flight.flight_ancilliaries;
const tf_GST = localizationData.flight.TF_GST;
const de_vat = localizationData.flight.de_VAT;
const trainBooking = localizationData.train.train_booking;
const trainVoid = localizationData.train.train_void;
const trainRefund = localizationData.train.train_refund;
const hotelBooking = localizationData.hotel.hotel_booking;
const hotelVoidBooking = localizationData.hotel.hotel_void;
const hotelRefundBooking = localizationData.hotel.hotel_refund;
const tf_Boarding = localizationData.flight.tf_priorityBoarding;

const flightsInvoiceValidationSelectors = {
  clickInvoiceTab: '.nav-item__wrapper:nth-child(2) span',
  viewItinerary: '[class^="bookings-flight-card__view"]',
  bookingCard: '.ta-booking-card',
  viewInvoice: '[qa-id="event-action-view-invoice"]',
  viewViewTripFee: '[qaid="eventActionViewTripFee"]',
  downloadInvoice: '.action--change-v2',
  downloadInvoiceLink: '[qa-id="event-action-download-invoice"]',
  flightBookingId: '.trip-event-card-flight__booking-info__row div',
  totalBookingChargeOnItinerary: '.trip-event-card-flight__booking-info__row div',
  totalBookingCurrencyOnItinerary: '.trip-event-card-flight__booking-info__row div',
  flightName: '.ta-trip-event-flight-details__title',
  invoiceBookingNameId: '[.title__main]',
  invoiceBookingId: '[data-testid="bookingId"]',
  invoiceFlightName: '[qaid="provider-name"]',
  invoiceTotalPrice: '[data-testid="totalTotal"]',
  invoicePriceTaxRate: '[data-testid="priceTaxRate"]',
  invoicePriceTax: '[data-testid="priceTax"]',
  flightCheckoutPageSummary: '.checkout-card__content',
  totalBookingCharge: '.car-checkout__est-total div span:nth-child(1)',
  totalBookingChargeCurrency: '.car-checkout__est-total div span:nth-child(2)',
  tripFeeSummaryOfCharges: "//*[@title='Trip fee']",
  providerName: '[class^="trip-event-card-flight__flight-info__flight-card-operator"]',
  bookingDetails: '.trip-event-card-flight__booking-info__value',
  invoiceTicketNumber: '[data-testid="transactionId"]',
  invoiceCardNumber: '.payment-method',
  travelerName: '.ta-user-menu__name--user-name',
  totalPrice: '.trip-event-card-flight__booking-info__value'
};

export class FlightsInvoiceValidation {
  static visitTripsPage() {
    CommerceShared.visitTripsPage();
  }

  static selectFlightBooking() {
    cy.allure().logStep(`Select Flight and View Itinerary :`);
    cy.intercept(
      'GET',
      new RegExp(`/api/admin/bookings/${guidRegex}/passengers/${guidRegex}/tripItem`)
    ).as('request');
    cy.get(flightsInvoiceValidationSelectors.bookingCard).should('be.visible');
    cy.get(flightsInvoiceValidationSelectors.viewItinerary).eq(0).click();
    cy.wait('@request')
      .its('response')
      .then((response) => {
        expect(response?.statusCode).to.eq(200);
      });
  }

  static checkItineraryPageIsVisited() {
    cy.allure().logStep(` Routing to Itinerary Page :`);
    cy.url().should(
      'include',
      `/app/user2/trips/${guidRegex}/itinerary?flightUuid=${guidRegex}`
    );
  }

  static storeBookingData() {
    cy.get(flightsInvoiceValidationSelectors.totalBookingCharge).then((element) => {
      cy.task('putDataInCache', {
        key: 'totalBookingCharge',
        data: element.text().trim()
      });
    });
    cy.get(flightsInvoiceValidationSelectors.totalBookingChargeCurrency).then(
      (element) => {
        cy.task('putDataInCache', {
          key: 'totalBookingChargeCurrency',
          data: element.text().trim()
        });
      }
    );
  }

  static storeFlightTripItineraryTripData() {
    cy.get(flightsInvoiceValidationSelectors.flightBookingId)
      .eq(1)
      .then((element) => {
        cy.task('putDataInCache', {
          key: 'bookingID',
          data: element.text().trim()
        });
      });
  }

  static clickAndDownloadInvoice() {
    cy.allure().logStep(` Go to view invoice page :`);
    cy.reload();
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    CommerceShared.visitViewInvoicePage();
    cy.wait(Timeouts.MEDIUM_TIMEOUT_60_SEC.timeout);
  }

  static checkInvoiceBookingId() {
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    cy.allure().logStep(` Check booking Id :`);
    cy.task<string>('getDataFromCache', 'bookingID').then((flightBookingId) => {
      cy.contains(flightBookingId);
    });
  }

  static checkInvoiceTotalPrice() {
    cy.allure().logStep(` Check total price :`);
    cy.task<string>('getDataFromCache', 'totalPrice').then((totalPrice) => {
      cy.contains(totalPrice);
    });
  }

  static checkInvoicePriceSalesTax() {
    cy.allure().logStep(` Check Invoice Price Tax :`);
    cy.task<string>('getDataFromCache', 'invoicePriceTax').then((invoicePriceTax) => {
      cy.contains(invoicePriceTax);
    });
  }

  static checkInvoicePriceSalesTaxRate() {
    cy.allure().logStep(` ChCheck Invoice Price Tax Rate :`);
    cy.task<string>('getDataFromCache', 'invoicePriceTaxRate').then(
      (invoicePriceTaxRate) => {
        cy.contains(invoicePriceTaxRate);
      }
    );
  }

  static visitViewTripFeePage() {
    cy.allure().logStep(` Go to view View Trip Fee Page :`);
    cy.reload();
    cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
    cy.get(flightsInvoiceValidationSelectors.downloadInvoiceLink).click();
    cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
  }

  static validateBookingDetails() {
    //TODO: since we have auto ticketing as part of booking will comment this out for now
    //FlightUtility.ticketSabreFlight();
    Utility.loginAsAdmin(adminCreds);
    cy.task('getDataFromCache', 'ItineraryURL').then((searchURL: any) => {
      cy.visit(searchURL);
    });
    FlightItinerary.waitToBeLoaded();
    FlightUtility.storeFlightBookingInformation();
    FlightUtility.verifyTripFeeInInvoice();
  }

  static checkInvoiceTripSalesTAXFee() {
    cy.allure().logStep(` Validate Trip Salex Tax Price :`);
    cy.task<string>('getDataFromCache', 'tripFee').then((tripFee) => {
      cy.allure().logStep(` Go to invoice trip fee tab and Check Tax Fee :`);
      cy.contains(tripFee);
    });
  }

  static checkInvoiceTAFee() {
    cy.task<string>('getDataFromCache', 'tripFee').then((tripFee) => {
      cy.allure().logStep(` Check TripActions Fee :`);
      cy.contains(tripFee);
    });
  }

  static checkInvoiceTAFeeDoesNotExist() {
    cy.allure().logStep('Vefify Trip Fee Section does not exist');
    cy.task('getDataFromCache', 'tripFee').then(() => {
      cy.allure().logStep(` Go to invoice trip fee tab and Check TripActions Fee :`);
      cy.get(flightsInvoiceValidationSelectors.clickInvoiceTab).should('not.be.visible');
    });
  }

  static checkTripFeeInCheckoutPageSummary() {
    cy.task('getDataFromCache', 'tripFee').then((tripFee) => {
      cy.get(flightsInvoiceValidationSelectors.flightCheckoutPageSummary)
        .should('contain', tripFee)
        .should('be.exist');
    });
  }

  static checkTripFeeInCheckoutPageSummaryShouldNotExist() {
    cy.get(flightsInvoiceValidationSelectors.flightCheckoutPageSummary).should(
      'be.visible'
    );
  }

  static checkBookingTotalPriceOnItineraryPage() {
    cy.allure().logStep(` Check Booking Total Price :`);
    cy.task('getDataFromCache', 'flightBookingTotalCharges').then(
      (totalBookingCharge) => {
        cy.get(flightsInvoiceValidationSelectors.totalBookingChargeOnItinerary)
          .eq(7)
          .should(($el) => {
            expect($el.text().trim()).contains(totalBookingCharge);
          });
      }
    );
    cy.task('getDataFromCache', 'flightBookingTotalChargesCurrency').then(
      (totalBookingChargeCurrency) => {
        cy.get(flightsInvoiceValidationSelectors.totalBookingCurrencyOnItinerary).should(
          ($el) => {
            expect($el.text().trim()).contains(totalBookingChargeCurrency);
          }
        );
      }
    );
  }
  static checkFlightsInvoice() {
    cy.allure().logStep(` Check Hotel name :`);
    cy.task('getDataFromCache', 'hotelName').then((hotelName) => {
      Utility.getIframeBody()
        .find(flightsInvoiceValidationSelectors.invoiceFlightName)
        .eq(0)
        .should(($el) => {
          expect($el.text().trim()).to.equal(hotelName);
        });
    });
  }
  static storeProvider() {
    cy.get(flightsInvoiceValidationSelectors.providerName)
      .eq(0)
      .then((el) => {
        cy.task('putDataInCache', {
          key: 'provider',
          data: el.text()
        });
      });
  }

  static storeTicketNumber() {
    cy.get(flightsInvoiceValidationSelectors.bookingDetails)
      .eq(1)
      .then((el) => {
        cy.task('putDataInCache', {
          key: 'ticketNumber',
          data: el.text()
        });
      });
  }

  static checkInvoiceTicketNumber() {
    cy.allure().logStep(` Check Ticket Number :`);
    cy.task<string>('getDataFromCache', 'ticketNumber').then((ticketNumber) => {
      cy.contains(ticketNumber);
    });
  }

  static checkInvoiceCardDigits(index: number) {
    cy.allure().logStep(` Check Last 4 Digits of Credit Card :`);
    cy.task('getDataFromCache', 'cardNumber').then((cardNumber) => {
      Utility.getIframeBody()
        .find(flightsInvoiceValidationSelectors.invoiceCardNumber)
        .eq(index)
        .then((el) => {
          expect(el.text()).contains(cardNumber);
        });
    });
  }
  static checkVoidInvoiceContent() {
    cy.allure().logStep(` Check Void Invoice content :`);
    cy.contains(english.TotalLabel);
    cy.contains(english.VoidTotalAmount);
    cy.contains(english.Void);
    cy.contains(english.Cancelled);
    cy.contains(english.VAT_Disclosure);
  }

  static checkUnchangeableInvoiceContent() {
    cy.allure().logStep(` Check Flight Unchangeability Invoice content :`);
    cy.contains(english.PaymentMethod);
    cy.contains(english.address);
    cy.contains(english.VAT_Disclosure);
    cy.contains(english.CorrectionOf);
    cy.contains(english.CreditNote);
    cy.contains(english.TaxInvoice);
  }
  static getTravelerName() {
    cy.get(flightsInvoiceValidationSelectors.travelerName)
      .eq(0)
      .then((el) => {
        cy.task('putDataInCache', {
          key: 'travelerName',
          data: el.text()
        });
      });
  }
  static storeTotalPrice() {
    cy.get(flightsInvoiceValidationSelectors.totalPrice)
      .eq(3)
      .then((el) => {
        const currencySymbol = el.text().match(/[A-Z]{3}/); // Extracts three consecutive uppercase letters (GBP)
        if (currencySymbol && currencySymbol.length > 0) {
          cy.task('putDataInCache', {
            key: 'ItineraryCurrencySymbol',
            data: currencySymbol[0]
          });
        } else {
          console.log('Currency symbol not found.');
        }
        cy.task('putDataInCache', {
          key: 'ItineraryTotalPrice',
          data: el.text()
        });
      });
  }

  static paymentXmlContentValidations() {
    cy.allure().logStep('Get Payment XML content from cache');
    Utility.getXmlContentFromCache(cacheKey).then((xmlContent: any) => {
      const xmlDoc = Utility.parseXmlContent(xmlContent);
      //amexAgcyNbrValue is TQ42
      const amexAgcyNbrElement = xmlDoc.getElementsByTagName('AmexAgcyNbr')[0];
      const amexAgcyNbrValue = amexAgcyNbrElement.textContent;
      expect(xmldata.AmexAgcyNbr).to.equal(
        amexAgcyNbrValue,
        'amexAgcyNbrValue is equal to xmldata.AmexAgcyNbr'
      );
      //amexOfcNbrValue is 032581516
      const amexOfcNbrElement = xmlDoc.getElementsByTagName('AmexOfcNbr')[0];
      const amexOfcNbrValue = amexOfcNbrElement.textContent;
      expect(xmldata.AmexOfcNbr).to.equal(
        amexOfcNbrValue,
        'amexOfcNbrValue is equal to xmldata.AmexOfcNbr'
      );
      //AcctNbr Value is Amex Card Number
      const acctNbrElement = xmlDoc.getElementsByTagName('AcctNbr')[0];
      const acctNbrdValue = acctNbrElement.textContent;
      expect(xmldata.FlightAcctNbr).to.equal(
        acctNbrdValue,
        'acctNbrdValue is equal to xmldata.FlightAcctNbr'
      );
      //CrdExpDt Value is Amex Card Expiry Date
      const crdExpDtElement = xmlDoc.getElementsByTagName('CrdExpDt')[0];
      const crdExpDtValue = crdExpDtElement.textContent;
      expect(xmldata.AMEXCrdExpDt).to.equal(
        crdExpDtValue,
        'crdExpDtValue is equal to xmldata.AMEXCrdExpDt'
      );
    });
  }
  static batchXmlContentValidations() {
    cy.allure().logStep('Get Flight Batch XML content from cache');
    Utility.getXmlContentFromCache(cacheKey).then((xmlContent: any) => {
      const xmlDoc = Utility.parseXmlContent(xmlContent);
      // btchCrCnValue is 0
      const btchCrCntElement = xmlDoc.getElementsByTagName('BtchCrCnt')[0];
      const btchCrCntValue = btchCrCntElement.textContent;
      expect(xmldata.FlightBtchCrCnt).to.equal(
        btchCrCntValue,
        'btchCrCntValue is equal to xmldata.FlightBtchCrCnt'
      );
      //BtchCrTot Value is 0
      const btchCrTotElement = xmlDoc.getElementsByTagName('BtchCrTot')[0];
      const btchCrTotValue = btchCrTotElement.textContent;
      expect(xmldata.FlightBtchCrCnt).to.equal(
        btchCrTotValue,
        'btchCrTotValue is equal to xmldata.FlightBtchCrCnt'
      );
      //btchCnt Value is 2
      const btchCntElement = xmlDoc.getElementsByTagName('BtchCnt')[0];
      const btchCntValue = btchCntElement.textContent;
      if (btchCntValue !== null) {
        expect(parseInt(btchCntValue)).to.be.at.least(
          1,
          'btchCntValue is equal to or greater than 1'
        );
      } else {
        cy.log('btchCntValue is not found');
      }
      //BtchSeqNbrValue is 8 digit number
      const btchSeqNbrElement = xmlDoc.getElementsByTagName('BtchSeqNbr')[0];
      const btchSeqNbrValue = btchSeqNbrElement.textContent;
      if (btchSeqNbrValue !== null && btchSeqNbrValue !== undefined) {
        expect(btchSeqNbrValue.trim().length).to.equal(8);
      } else {
        cy.log('BtchSeqNbrValue is null or undefined');
      }
      //BtchDbCrInd Value is D
      const btchDbCrIndElement = xmlDoc.getElementsByTagName('BtchDbCrInd')[0];
      const btchDbCrIndValue = btchDbCrIndElement.textContent;
      expect(xmldata.BtchDbCrInd).to.equal(
        btchDbCrIndValue,
        'btchDbCrIndValue is equal to xmldata.BtchDbCrInd'
      );
      //TrvlBtchCnt Value is traveler count
      const trvlBtchCntElement = xmlDoc.getElementsByTagName('TrvlBtchCnt')[0];
      const trvlBtchCntValue = trvlBtchCntElement.textContent;
      if (trvlBtchCntValue !== null) {
        expect(parseInt(trvlBtchCntValue)).to.be.at.least(
          1,
          'trvlBtchCntValue is equal to or greater than 1'
        );
      } else {
        cy.log('trvlBtchCntValue is not found');
      }
    });
  }
  static currencyCodeXmlContentValidations() {
    cy.allure().logStep('Get Currency XML content from cache');
    Utility.getXmlContentFromCache(cacheKey).then((xmlContent: any) => {
      const xmlDoc = Utility.parseXmlContent(xmlContent);
      cy.task('getDataFromCache', 'ItineraryCurrencySymbol').then((currency: any) => {
        //TrvlBtchCurrCd is currency code
        const trvlBtchCurrCdElement = xmlDoc.getElementsByTagName('TrvlBtchCurrCd')[0];
        const trvlBtchCurrCdValue = trvlBtchCurrCdElement.textContent;
        expect(currency).to.equal(
          trvlBtchCurrCdValue,
          'currency is equal to trvlBtchCurrCdValue'
        );
        //CurrencyCd is currency code
        const currencyCdElement = xmlDoc.getElementsByTagName('CurrencyCd')[0];
        const currencyCdValue = currencyCdElement.textContent;
        expect(currency).to.equal(
          currencyCdValue,
          'currency is equal to currencyCdValue'
        );
      });
    });
  }
  static travelerXmlContentValidations() {
    cy.allure().logStep('Get Traveler XML content from cache');
    Utility.getXmlContentFromCache(cacheKey).then((xmlContent: any) => {
      const xmlDoc = Utility.parseXmlContent(xmlContent);
      cy.task('getDataFromCache', 'travelerName').then((travelerName: any) => {
        //TODO: CustRefTx Value should be trip purpose and it should be same as traveler name: CM2-9248
        /*const custRefTxElement = xmlDoc.getElementsByTagName('CustRefTx')[0];
        const custRefTxValue = custRefTxElement.textContent;
        expect(custRefTxValue).to.equal(
          travelerName,
          'custRefTxValue is equal to travelerName'
        );*/
        const tvlrLastNmElement = xmlDoc.getElementsByTagName('TvlrLastNm')[0];
        const tvlrLastNmValue = tvlrLastNmElement.textContent;
        expect(travelerName).to.contains(
          tvlrLastNmValue,
          'travelerName contains tvlrLastNmValue'
        );
        const tvlrFirstNmElement = xmlDoc.getElementsByTagName('TvlrFirstNm')[0];
        const tvlrFirstNmValue = tvlrFirstNmElement.textContent;
        expect(travelerName).to.contains(
          tvlrFirstNmValue,
          'travelerName contains tvlrFirstNmValue'
        );
      });
      //travelTranCrCntValue Value is Credit transaction count
      const travelTranCrCntElement = xmlDoc.getElementsByTagName('TravelTranCrCnt')[0];
      const travelTranCrCntValue = travelTranCrCntElement.textContent;
      expect(xmldata.TravelTranCrCnt).to.equal(
        travelTranCrCntValue,
        'xmldata.TravelTranCrCnt is equal to travelTranCrCntValue'
      );
      //travelTranDbCntValue id Debit transaction count
      const travelTranDbCntElement = xmlDoc.getElementsByTagName('TravelTranDbCnt')[0];
      const travelTranDbCntValue = travelTranDbCntElement?.textContent; // Use optional chaining operator "?"
      if (travelTranDbCntValue !== null) {
        expect(parseInt(travelTranDbCntValue)).to.be.at.least(
          1,
          'TravelTranDbCnt is equal to or greater than 1'
        );
      } else {
        cy.log('TravelTranDbCnt is not found');
      }
      //SettleDbCrInd Value is D
      const settleDbCrIndElement = xmlDoc.getElementsByTagName('SettleDbCrInd')[0];
      const settleDbCrIndValue = settleDbCrIndElement.textContent;
      expect(xmldata.TravelDbCrInd).to.equal(
        settleDbCrIndValue,
        'xmldata.TravelDbCrInd is equal to settleDbCrIndValue'
      );
      //TravelDbCrInd Value is D
      const travelDbCrIndElement = xmlDoc.getElementsByTagName('TravelDbCrInd')[0];
      const travelDbCrIndValue = travelDbCrIndElement.textContent;
      expect(xmldata.TravelDbCrInd).to.equal(
        travelDbCrIndValue,
        'xmldata.TravelDbCrInd is equal to travelDbCrIndValue'
      );
    });
  }
  static flightXmlContentValidations() {
    Utility.getXmlContentFromCache(cacheKey).then((xmlContent: any) => {
      const xmlDoc = Utility.parseXmlContent(xmlContent);
      //commodityCdValue for flight is 001 or 009
      const commodityCdElement = xmlDoc.getElementsByTagName('CommodityCd')[0];
      const commodityCdValue = commodityCdElement.textContent;
      if (commodityCdValue !== null && commodityCdValue !== undefined) {
        expect(commodityCdValue.trim() === xmldata.CommodityCdFlight).to.be.true;
      } else {
        cy.log('CommodityCdValue is null or undefined');
      }
      //TransAmtValue is total charges
      /* cy.task('getDataFromCache', 'flightBookingTotalCharges').then((total: any) => {
        const transAmtElements = xmlDoc.getElementsByTagName('TransAmt');
        if (transAmtElements !== null && transAmtElements !== undefined) {
          const transAmtFirstElement = transAmtElements[0];
          const transAmtFirstValue = parseFloat(transAmtFirstElement.textContent || '0');
          // this is only need to if we don't have trip fee in the booking
          cy.task('getDataFromCache', 'tripFeeCheckOut').then((tripFee: any) => {
            const tripFeeCheckout = tripFee.replace(/[^0-9]/g, '');
            const totalCharges = transAmtFirstValue + parseFloat(tripFeeCheckout);
            const roundedTotalCharges = totalCharges - 1; // Round to two decimal places
            const strippedAmount = total.replace(/[^0-9]/g, '');
            cy.log('total:============' + roundedTotalCharges);
            cy.log('strippedAmount:============' + strippedAmount);
            expect(
              isWithinTolerance(roundedTotalCharges, strippedAmount, tolerance),
              'TransAmtValue is total charges'
            ).to.be.true;
          });
        } else {
          cy.log('TransAmt is not present in XML');
        }
        //BtchDbTot is total charges
        cy.task('getDataFromCache', 'tripFeeCheckOut').then((tripFee: any) => {
          const tripFeeCheckout = tripFee.replace(/[^0-9]/g, '');
          const btchDbTotElement = xmlDoc.getElementsByTagName('BtchDbTot')[0];
          const btchDbTotValue = parseFloat(btchDbTotElement.textContent || '0');
          const totalCharges = btchDbTotValue + parseFloat(tripFeeCheckout);
          const roundedTotalCharges = totalCharges - 1;
          const strippedAmount = total.replace(/[^0-9]/g, '');
          expect(
            isWithinTolerance(roundedTotalCharges, strippedAmount, tolerance),
            'BtchDbTot is total charges'
          ).to.be.true;
        });
        //TravelTranTot is total charges
        cy.task('getDataFromCache', 'tripFeeCheckOut').then((tripFee: any) => {
          const tripFeeCheckout = tripFee.replace(/[^0-9]/g, '');
          const travelTranTotElement = xmlDoc.getElementsByTagName('TravelTranTot')[0];
          const travelTranTotValue = parseFloat(travelTranTotElement.textContent || '0');
          const totalCharges = travelTranTotValue + parseFloat(tripFeeCheckout);
          const roundedTotalCharges = totalCharges - 1;
          const strippedAmount = total.replace(/[^0-9]/g, '');
          expect(
            isWithinTolerance(roundedTotalCharges, strippedAmount, tolerance),
            'TravelTranTot is total charges'
          ).to.be.true;
        });
        //BtchTot is total charges
        cy.task('getDataFromCache', 'tripFeeCheckOut').then((tripFee: any) => {
          const tripFeeCheckout = tripFee.replace(/[^0-9]/g, '');
          const btchTotElement = xmlDoc.getElementsByTagName('BtchTot')[0];
          const btchTotValue = parseFloat(btchTotElement.textContent || '0');
          const totalCharges = btchTotValue + parseFloat(tripFeeCheckout);
          const roundedTotalCharges = totalCharges - 1;
          const strippedAmount = total.replace(/[^0-9]/g, '');
          expect(
            isWithinTolerance(roundedTotalCharges, strippedAmount, tolerance),
            'BtchTot is total charges'
          ).to.be.true;
        });
        //TravelTranTot is total charges
        cy.task('getDataFromCache', 'tripFeeCheckOut').then((tripFee: any) => {
          const tripFeeCheckout = tripFee.replace(/[^0-9]/g, '');
          const travelTranDbTotElement =
            xmlDoc.getElementsByTagName('TravelTranDbTot')[0];
          const travelTranDbTotValue = parseFloat(
            travelTranDbTotElement.textContent || '0'
          );
          const totalCharges = travelTranDbTotValue + parseFloat(tripFeeCheckout);
          const roundedTotalCharges = totalCharges - 1;
          const strippedAmount = total.replace(/[^0-9]/g, '');
          expect(
            isWithinTolerance(roundedTotalCharges, strippedAmount, tolerance),
            'TravelTranDbTot is total charges'
          ).to.be.true;
        });
      });*/
      //AirTransTypeCd Value is TKT
      const airTransTypeCdElement = xmlDoc.getElementsByTagName('AirTransTypeCd')[0];
      const airTransTypeCdValue = airTransTypeCdElement.textContent;
      expect(xmldata.AirTransTypeCd).to.equal(
        airTransTypeCdValue,
        'xmldata.AirTransTypeCd is equal to airTransTypeCdValue'
      );
      // ArrAirCd Value is arrival location
      cy.task('getDataFromCache', 'arrivalLocation').then((arrivalLocation: any) => {
        const arrAirCdElement = xmlDoc.getElementsByTagName('ArrAirCd')[0];
        const arrAirCdValueLocation = arrAirCdElement.textContent;
        expect(arrivalLocation).to.equal(
          arrAirCdValueLocation,
          'arrivalLocation is equal to arrAirCdValueLocation'
        );
      });
      //TktIssDt Value is YYYYMMDD
      const tktIssDtElement = xmlDoc.getElementsByTagName('TktIssDt')[0];
      const flightTktIssDtValue = tktIssDtElement.textContent;
      if (flightTktIssDtValue !== null && flightTktIssDtValue !== undefined) {
        expect(flightTktIssDtValue.trim()).to.match(
          dateFormatPattern,
          'flightTktIssDtValue is in YYYYMMDD format'
        );
      } else {
        cy.log('DestNmValue is not in YYYYMMDD format');
      }
      // DprtAirCd Value is departure location
      cy.task('getDataFromCache', 'departureLocation').then((departureLocation: any) => {
        const dprtAirCdElement = xmlDoc.getElementsByTagName('DprtAirCd')[0];
        const dprtAirCdValueLocation = dprtAirCdElement.textContent;
        expect(departureLocation).to.equal(
          dprtAirCdValueLocation,
          'departureLocation is equal to dprtAirCdValueLocation'
        );
      });
      // SuplrNm Value is airline name
      cy.task('getDataFromCache', 'airline').then((airline: any) => {
        const suplrNmElement = xmlDoc.getElementsByTagName('SuplrNm')[0];
        const suplrNmCdName = suplrNmElement.textContent;
        expect(airline).to.equal(suplrNmCdName, 'airline is equal to suplrNmCdName');
      });
      cy.task('getDataFromCache', 'airlineCode').then((airlineCode: any) => {
        //CarrierCd Value is airline code
        const carrierCdElement = xmlDoc.getElementsByTagName('CarrierCd')[0];
        const carrierCdCode = carrierCdElement.textContent;
        expect(airlineCode).to.equal(
          carrierCdCode,
          'airlineCode is equal to carrierCdCode'
        );
      });
      //SctrTypeCd Value is A
      const sctrTypeCdElement = xmlDoc.getElementsByTagName('SctrTypeCd')[0];
      const sctrTypeCd = sctrTypeCdElement.textContent;
      expect(xmldata.SctrTypeCd).to.equal(
        sctrTypeCd,
        'xmldata.SctrTypeCd is equal to sctrTypeCd'
      );
      cy.task('getDataFromCache', 'flightNumber').then((flightNumber: any) => {
        //FlightNbr Value is flight number
        const flightNbrElement = xmlDoc.getElementsByTagName('FlightNbr')[0];
        const flightNbr = flightNbrElement.textContent;
        expect(flightNumber).to.equal(flightNbr, 'flightNumber is equal to flightNbr');
      });
      //DomesticInd Value is Y
      const domesticIndElement = xmlDoc.getElementsByTagName('DomesticInd')[0];
      const domesticInd = domesticIndElement.textContent;
      expect(xmldata.DomesticInd).to.equal(
        domesticInd,
        'xmldata.DomesticInd is equal to domesticInd'
      );
    });
  }
  static sabreFlightXmlContentValidations() {
    Utility.getXmlContentFromCache(cacheKey).then((xmlContent: any) => {
      const xmlDoc = Utility.parseXmlContent(xmlContent);
      //commodityCdValue for trip fee is 001 or 009
      const commodityCdElementFee = xmlDoc.getElementsByTagName('CommodityCd')[1];
      const commodityCdValueFee = commodityCdElementFee.textContent;
      if (commodityCdValueFee !== null && commodityCdValueFee !== undefined) {
        expect(
          commodityCdValueFee.trim() === xmldata.CommodityCdFlight ||
            commodityCdValueFee === xmldata.CommodityCdTripFee
        ).to.be.true;
      } else {
        cy.log('CommodityCdValue is null or undefined');
      }
      //commodityCdValue for flight is 001 or 009
      const commodityCdElement = xmlDoc.getElementsByTagName('CommodityCd')[0];
      const commodityCdValue = commodityCdElement.textContent;
      if (commodityCdValue !== null && commodityCdValue !== undefined) {
        expect(
          commodityCdValue.trim() === xmldata.CommodityCdFlight ||
            commodityCdValue === xmldata.CommodityCdTripFee
        ).to.be.true;
      } else {
        cy.log('CommodityCdValue is null or undefined');
      }
      //TransAmtValue is total charges
      cy.task('getDataFromCache', 'flightBookingTotalCharges').then((total: any) => {
        const transAmtElements = xmlDoc.getElementsByTagName('TransAmt');
        if (transAmtElements.length >= 2) {
          const transAmtFirstElement = transAmtElements[0];
          const transAmtFirstValue = parseFloat(transAmtFirstElement.textContent || '0');
          const transAmtSecondElement = transAmtElements[1];
          const transAmtSecondValue = parseFloat(
            transAmtSecondElement.textContent || '0'
          );
          const totalCharges = transAmtFirstValue + transAmtSecondValue;
          const strippedAmount = total.replace(/[^0-9]/g, '');
          expect(strippedAmount).to.contains(totalCharges);
        } else {
          cy.log('TransAmt is not present in XML');
        }
        //BtchDbTot is total charges
        const btchDbTotElement = xmlDoc.getElementsByTagName('BtchDbTot')[0];
        const btchDbTotValue = parseFloat(btchDbTotElement.textContent || '0');
        const strippedAmount = total.replace(/[^0-9]/g, '');
        expect(strippedAmount).to.contains(
          btchDbTotValue,
          'strippedAmount is equal to btchDbTotValue'
        );
        //TravelTranTot is total charges
        const travelTranTotElement = xmlDoc.getElementsByTagName('TravelTranTot')[0];
        const travelTranTotValue = parseFloat(travelTranTotElement.textContent || '0');
        expect(strippedAmount).to.contains(
          travelTranTotValue,
          'strippedAmount is equal to travelTranTotValue'
        );
        //BtchTot is total charges
        const btchTotElement = xmlDoc.getElementsByTagName('BtchTot')[0];
        const btchTotValue = parseFloat(btchTotElement.textContent || '0');
        expect(strippedAmount).to.contains(
          btchTotValue,
          'strippedAmount is equal to btchTotValue'
        );
        //TravelTranTot is total charges
        const travelTranDbTotElement = xmlDoc.getElementsByTagName('TravelTranDbTot')[0];
        const travelTranDbTotValue = parseFloat(
          travelTranDbTotElement.textContent || '0'
        );
        expect(strippedAmount).to.contains(
          travelTranDbTotValue,
          'strippedAmount is equal to travelTranDbTotValue'
        );
      });
      cy.task('getDataFromCache', 'ticketNumber').then((ticketNumber: any) => {
        //InvNbr is last 9 digits of ticket number
        const lastNineDigits = ticketNumber.trim().slice(-9);
        const invNbrrElement = xmlDoc.getElementsByTagName('InvNbr')[0];
        const invNbrValue = invNbrrElement.textContent;
        expect(lastNineDigits).to.equal(
          invNbrValue,
          'lastNineDigits is equal to invNbrValue'
        );
        //we have defect for TktNbr once it is fixed we can uncomment below code
        // TktNbr is ticket number
        /*const tktNbrElement = xmlDoc.getElementsByTagName('TktNbr')[0];
        const tktNbrValue = tktNbrElement.textContent;
        expect(ticketNumber).to.equal(tktNbrValue);*/
      });
      //AirTransTypeCd Value is TKT
      const airTransTypeCdElement = xmlDoc.getElementsByTagName('AirTransTypeCd')[0];
      const airTransTypeCdValue = airTransTypeCdElement.textContent;
      expect(xmldata.AirTransTypeCd).to.equal(
        airTransTypeCdValue,
        'xmldata.AirTransTypeCd is equal to airTransTypeCdValue'
      );
      //TktIssDt Value is YYYYMMDD
      const tktIssDtElement = xmlDoc.getElementsByTagName('TktIssDt')[0];
      const tktIssDtValue = tktIssDtElement.textContent;
      if (tktIssDtValue !== null && tktIssDtValue !== undefined) {
        expect(tktIssDtValue.trim()).to.match(
          dateFormatPattern,
          'tktIssDtValue is in YYYYMMDD format'
        );
      } else {
        cy.log('DestNmValue is not in YYYYMMDD format');
      }
      // ArrAirCd Value is arrival location
      cy.task('getDataFromCache', 'arrivalLocation').then((arrivalLocation: any) => {
        const arrAirCdElement = xmlDoc.getElementsByTagName('ArrAirCd')[0];
        const arrAirCdValue = arrAirCdElement.textContent;
        expect(arrivalLocation).to.equal(
          arrAirCdValue,
          'arrivalLocation is equal to arrAirCdValue'
        );
      });
      // DprtAirCd Value is departure location
      cy.task('getDataFromCache', 'departureLocation').then((departureLocation: any) => {
        const dprtAirCdElement = xmlDoc.getElementsByTagName('DprtAirCd')[0];
        const dprtAirCdValue = dprtAirCdElement.textContent;
        expect(departureLocation).to.equal(
          dprtAirCdValue,
          'departureLocation is equal to dprtAirCdValue'
        );
      });
      // SuplrNm Value is airline name
      cy.task('getDataFromCache', 'airline').then((airline: any) => {
        const suplrNmElement = xmlDoc.getElementsByTagName('SuplrNm')[0];
        const suplrNmCdValue = suplrNmElement.textContent;
        expect(airline).to.equal(suplrNmCdValue, 'airline is equal to suplrNmCdValue');
      });
      cy.task('getDataFromCache', 'airlineCode').then((airlineCode: any) => {
        //CarrierCd Value is airline code
        const carrierCdElement = xmlDoc.getElementsByTagName('CarrierCd')[0];
        const carrierCdValue = carrierCdElement.textContent;
        expect(airlineCode).to.equal(
          carrierCdValue,
          'airlineCode is equal to carrierCdValue'
        );
      });
      cy.task('getDataFromCache', 'flightNumber').then((flightNumber: any) => {
        //FlightNbr Value is flight number
        const flightNbrElement = xmlDoc.getElementsByTagName('FlightNbr')[0];
        const flightNbrValue = flightNbrElement.textContent;
        expect(flightNumber).to.equal(
          flightNbrValue,
          'flightNumber is equal to flightNbrValue'
        );
      });
      //SctrTypeCd Value is A
      const sctrTypeCdElement = xmlDoc.getElementsByTagName('SctrTypeCd')[0];
      const sctrTypeCdValue = sctrTypeCdElement.textContent;
      expect(xmldata.SctrTypeCd).to.equal(
        sctrTypeCdValue,
        'xmldata.SctrTypeCd is equal to sctrTypeCdValue'
      );
      //DomesticInd Value is Y
      const domesticIndElement = xmlDoc.getElementsByTagName('DomesticInd')[0];
      const domesticIndValue = domesticIndElement.textContent;
      expect(xmldata.DomesticInd).to.equal(
        domesticIndValue,
        'xmldata.DomesticInd is equal to domesticIndValue'
      );
    });
  }
  static getLedgerDataByBookingUUID() {
    cy.task('getDataFromCache', 'bookingUuid').then((bookingUuid: any) => {
      cy.getLedgerData(bookingUuid);
    });
  }
  static validateVatAmount() {
    cy.task('getDataFromCache', 'ledgerData').then((ledgerData: any) => {
      const totalVatAmount = ledgerData.transactions[0].total_vat_amount.amount;
      const formattedAmount = totalVatAmount.toFixed(2);
      const vatRate = ledgerData.transactions[0].vat_rate;
      const vatId = ledgerData.transactions[0].metadata.find(
        (item: any) => item.name === 'vat_id'
      ).value;

      cy.allure().logStep('Check VAT amount in Invoice:');
      cy.contains(formattedAmount);

      cy.allure().logStep('Check VAT rate in Invoice:');
      cy.contains(vatRate);

      cy.allure().logStep('Check VAT ID in Invoice:');
      cy.contains(vatId);
    });
  }
  static tfInvoiceValidations() {
    cy.task('getDataFromCache', 'ledgerData').then((ledgerData: any) => {
      const totalAmount = ledgerData.total_amount.amount;
      const formattedAmount = totalAmount.toFixed(2);
      const vatId = ledgerData.transactions[1].metadata.find(
        (item: any) => item.name === 'vat_id'
      ).value;
      const supplierName = ledgerData.transactions[1].metadata.find(
        (item: any) => item.name === 'supplier_name'
      ).value;
      const tripFee = ledgerData.transactions[0].total_amount.amount;
      const formattedTripFee = tripFee.toFixed(2);
      cy.allure().logStep('Check Total amount in Invoice:');
      cy.contains(formattedAmount);
      cy.allure().logStep('Check VAT ID in Invoice:');
      cy.contains(vatId);
      cy.allure().logStep('Check supplier name in Invoice:');
      cy.contains(supplierName);
      cy.task('getDataFromCache', 'bookingID').then((bookingID: any) => {
        cy.allure().logStep('Check BookingID in Invoice:');
        cy.contains(bookingID);
      });
      cy.allure().logStep('Check Trip Fee in Invoice:');
      cy.contains(formattedTripFee);
    });
  }
  static visitItineraryPage(url: string) {
    cy.visit(url);
    cy.wait(Timeouts.MEDIUM_TIMEOUT_60_SEC.timeout);
    cy.reload();
  }
  static validateFlightInvoiceDetails() {
    cy.contains(english.FlightReceipt);
    //Skipping this: cy. contains(english.NavanFee);
    //Skipping this: cy. contains(english.NavanTripFee);
    cy.contains(english.bookingID);
    //Skipping this: cy. contains(english.PaymentMethod);
  }
  static validateFlightTaxInvoiceDetails() {
    cy.contains(english.TaxInvoice);
    cy.contains(english.NavanFee);
    cy.contains(english.NavanTripFee);
    cy.contains(english.PaymentMethod);
  }
  static validateTDSTripFeeInvoiceDetails() {
    cy.contains(english.NavanTripFee);
    cy.contains(tdsIndia.bookingID);
    cy.contains(tdsIndia.CGST);
    cy.contains(tdsIndia.SGST);
    cy.contains(tdsIndia.withHoldTax);
    cy.contains(tdsIndia.rs);
    cy.contains(tdsIndia.signature);
    cy.contains(english.VAT_Disclosure);
  }
  static validateFlightVoidInvoiceDetails() {
    cy.contains(english.FlightReceipt);
    cy.contains(english.NavanFee);
    cy.contains(english.NavanTripFee);
    cy.contains(flightVoid.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(english.Void);
    cy.contains(english.VoidTotalAmount);
  }
  static validateFlightExchangeInvoiceDetails() {
    cy.contains(english.FlightReceipt);
    cy.contains(english.NavanFee);
    cy.contains(english.NavanTripFee);
    cy.contains(flightExchange.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(flightExchange.exchange);
    cy.contains(flightExchange.exchangeTotalAmount);
    cy.contains(flightExchange.collected_amount);
  }
  static validateFlightRefundInvoiceDetails() {
    cy.contains(english.FlightReceipt);
    cy.contains(english.NavanFee);
    cy.contains(english.NavanTripFee);
    cy.contains(flightRefund.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(flightRefund.refund);
    cy.contains(english.VoidTotalAmount);
  }
  static validateFlightAncilliaryInvoiceDetails() {
    cy.contains(english.FlightReceipt);
    cy.contains(flightAncilliaries.bookingID);
    cy.contains(flightAncilliaries.baggage);
    cy.contains(flightAncilliaries.seat);
    cy.contains(flightAncilliaries.baggage_ticketNumber);
    cy.contains(flightAncilliaries.baggage_collected_amount);
    cy.contains(flightAncilliaries.seat_collected_amount);
  }
  static validateTFFlightSupplierDetails() {
    cy.contains(english.invoice);
    cy.contains(english.NavanTripFee);
    cy.contains(tf_GST.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(tf_GST.Au_currency);
    cy.contains(tf_GST.totalAmount);
  }
  static validateDE_VATInvoiceValidations() {
    cy.contains(english.TaxInvoice);
    cy.contains(de_vat.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(de_vat.gbp);
    cy.contains(de_vat.baseAmount);
    cy.contains(de_vat.vat_percentage);
    cy.contains(de_vat.vat_tax);
  }
  static validateTrainInvoiceDetails() {
    cy.contains(english.TrainReceipt);
    cy.contains(trainBooking.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(trainBooking.totalAmount);
  }
  static validateRailVoidInvoiceDetails() {
    cy.contains(english.TrainReceipt);
    cy.contains(trainVoid.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(english.Void);
    cy.contains(english.VoidTotalAmount);
    cy.contains(english.baseAmount);
  }
  static validateRailRefundInvoiceDetails() {
    cy.contains(english.TrainReceipt);
    cy.contains(trainRefund.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(trainRefund.trainRefund);
    cy.contains(english.VoidTotalAmount);
    cy.contains(english.baseAmount);
  }
  static validateHotelInvoiceDetails() {
    cy.contains(english.HotelReceipt);
    cy.contains(hotelBooking.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(english.baseAmount);
    cy.contains(english.visaCard);
    //Skipping this: cy. contains(english.NavanFee);
    //Skipping this: cy. contains(english.NavanTripFee);
  }
  static validateHotelVoidInvoiceDetails() {
    cy.contains(english.HotelReceipt);
    cy.contains(hotelVoidBooking.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(english.baseAmount);
    cy.contains(english.visaCard);
    //Skipping this: cy. contains(english.NavanFee);
    //Skipping this: cy. contains(english.NavanTripFee);
    cy.contains(english.Void);
    cy.contains(english.VoidTotalAmount);
  }
  static validateHotelRefundInvoiceDetails() {
    cy.contains(english.HotelReceipt);
    cy.contains(hotelRefundBooking.bookingID);
    cy.contains(english.PaymentMethod);
    cy.contains(hotelRefundBooking.refund);
    cy.contains(english.VoidTotalAmount);
    cy.contains(english.baseAmount);
  }
  static validateTFFlightPriorityBoardingDetails() {
    //Skipping this: cy. contains(english.TaxInvoice);
    //Skipping this: cy. contains(english.NavanTripFee);
    cy.contains(tf_Boarding.tripUrlBookingId); // booking associated with tripUrl
    //Skipping this: cy. contains(english.PaymentMethod);
    //Skipping this: cy. contains(tf_Boarding.priorityBoardingAmount);
    //Skipping this: cy. contains(tf_Boarding.priorityBoarding);
    //Skipping this: cy. contains(tf_Boarding.totalAmount);
  }
  static reloadPage() {
    cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
    cy.reload();
  }
}
