import { xmlEu } from '@fixtures/commerce/xml/xml_eu';
const xmlData = xmlEu.xmlDataFlight;
const edfData = xmlEu.edfFileData;
const cacheKey = xmlData.cacheKey;
const currentDate = new Date()
  .toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: '2-digit' })
  .replace(/\//g, '');
export class Edf {
  static getEdfFile() {
    cy.allure().logStep('Get EDF content from cache');
    return cy.task('getDataFromCache', cacheKey).then((response: any) => {
      const edfContent = response.xmlReports[0];
      return cy.wrap(edfContent);
    });
  }
  static edfFooterValidations() {
    cy.allure().logStep('EDF Footer validations');
    this.getEdfFile().then((edfContent: any) => {
      if (edfContent.endsWith(edfData.footerStatsWith)) {
        const lines = edfContent.split('\n');
        const footer = lines.find((line: any) => line.startsWith('9999'));
        const footerStarts = footer.substring(0, 4);
        //footer starts with 9999 position 1-4
        if (footer.startsWith(edfData.footerStatsWith)) {
          cy.log(
            'EDF file footer starts with expected ' +
              edfData.footerStatsWith +
              ' actual: ' +
              footerStarts
          );
        } else {
          throw new Error(
            'EDF file footer does not starts with expected ' +
              edfData.footerStatsWith +
              ' actual: ' +
              footerStarts
          );
        }
      }
    });
  }
  static edfFlightValidations() {
    cy.allure().logStep('EDF Flight Booking validations');
    this.getEdfFile().then((edfContent: any) => {
      const stringEDFContent = String(edfContent);
      const keys = [
        'ticketNumber',
        'airlineCode',
        'airline',
        'flightNumber',
        'departureLocation',
        'arrivalLocation',
        'bookingID'
      ];

      keys.forEach((key) => {
        cy.task('getDataFromCache', key).then((value: any) =>
          this.checkInclusion(stringEDFContent, key, value)
        );
      });
    });
  }

  static checkInclusion(edfContent: string, key: string, value: any) {
    expect(edfContent.includes(value), `${key} is not included in EDF file`);
    cy.log(
      `${key} is included in EDF file as expected. ` + `${value} contains in EDF file.`
    );
  }
  static edfFileContentValidations() {
    cy.allure().logStep('EDF file required validations');
    this.getEdfFile().then((edfContent: any) => {
      const stringEDFContent = String(edfContent);
      const pairs = [
        { start: 0, end: 4, value: edfData.headerStatsWith, msg: 'Header value' },
        { start: 4, end: 10, value: currentDate, msg: 'Created date' },
        {
          start: 10,
          end: 14,
          value: edfData.amexValueForTravelAgent,
          msg: 'Amex value for travel agent'
        },
        {
          start: 23,
          end: 33,
          value: edfData.travelAgentMerchantNumber,
          msg: 'Travel agent merchant number'
        },
        { start: 33, end: 63, value: edfData.travelAgentName, msg: 'Travel agent name' }
      ];

      pairs.forEach((pair) => {
        const actualValue = edfContent.slice(pair.start, pair.end);
        if (actualValue === pair.value) {
          cy.log(
            `EDF file ${pair.msg} is as expected: ${pair.value} actual: ${actualValue}`
          );
        } else {
          throw new Error(
            `EDF file ${pair.msg} does not start with: ${pair.value} actual: ${actualValue}`
          );
        }
      });
      // Currency validation in EDF file
      expect(
        edfContent.includes(edfData.currency),
        edfData.currency + ` is not included in EDF file`
      );
      cy.log(edfData.currency + ` is included in EDF file as expected.`);

      // Payment card number validation in EDF file
      cy.task('getDataFromCache', 'paymentMethod').then(
        this.verifyCardNumber.bind(null, stringEDFContent)
      );
    });
  }

  static verifyCurrency(edfContent: any, currencyCode: any) {
    const currency = edfContent.slice(63, 66);
    if (currency === currencyCode) {
      cy.log(`EDF file currency is expected: ${currencyCode} actual: ${currency}`);
    } else {
      throw new Error(
        `EDF file currency is not as expected: ${currencyCode} actual: ${currency}`
      );
    }
  }
  static edfTravelerValidations() {
    cy.allure().logStep('EDF file Traveler validations');
    cy.task('getDataFromCache', 'travelerName').then((travelerName: any) => {
      const firstName = travelerName.split(' ')[0];
      const lastName = travelerName.split(' ')[1];
      this.getEdfFile().then((edfContent: any) => {
        const stringEDFContent = String(edfContent);
        expect(
          stringEDFContent.includes(firstName),
          `${firstName} is not included in EDF file`
        );
        cy.log(`${firstName} is included in EDF file as expected.`);
        expect(
          stringEDFContent.includes(lastName),
          `${lastName} is not included in EDF file`
        );
        cy.log(`${lastName} is included in EDF file as expected.`);
      });
    });
  }

  static usEdfFileValidations() {
    cy.allure().logStep('EDF file Required validations');

    this.getEdfFile().then((edfContent: any) => {
      const stringEDFContent = String(edfContent);
      //current date validation in EDF file
      expect(
        stringEDFContent.includes(currentDate),
        currentDate + `Current date is included in EDF file`
      );
      //Flight booking ID validation in EDF file
      cy.task('getDataFromCache', 'bookingID').then((bookingID: any) => {
        expect(
          stringEDFContent.includes(bookingID),
          bookingID + `Booking ID is included in EDF file`
        );
      });
      //TODO: Expected value is 16 digits but EDF file contains 15 digits once it is fixed will uncomment below line CM2-9279
      //Credit card number validation in EDF file
      //expect(stringEDFContent.includes(edfData.fareLogixCardNumber), edfData.fareLogixCardNumber + `Credit card number is included in EDF file`);
    });
  }
  static usEdfFileFlightValidations() {
    cy.allure().logStep('US EDF file Flight validations');

    this.getEdfFile().then((edfContent: any) => {
      const stringEDFContent = String(edfContent);
      //Indicator validation in EDF file
      expect(
        stringEDFContent.includes(edfData.usFlightIndicator),
        edfData.usFlightIndicator + `Indicator is included in EDF file`
      );
      //Domestic indicator validation in EDF file
      expect(
        stringEDFContent.includes(edfData.usFlightDomesticIndicator),
        edfData.usFlightDomesticIndicator + `Domestic indicator is included in EDF file`
      );
      cy.task('getDataFromCache', 'ticketNumber').then((ticketNumber: any) => {
        //Ticket number validation in EDF file
        const lastTenDigits = ticketNumber.slice(-10);
        expect(
          stringEDFContent.includes(lastTenDigits),
          lastTenDigits + `Ticket number is included in EDF file`
        );
      });
    });
  }
  static usEdfFileRailValidations() {
    cy.allure().logStep('US EDF file Flight validations');

    this.getEdfFile().then((edfContent: any) => {
      const stringEDFContent = String(edfContent);
      //account number validation in EDF file
      expect(
        stringEDFContent.includes(edfData.amexCardNumber),
        edfData.amexCardNumber + `Indicator is included in EDF file`
      );
      //Rail indicator validation in EDF file
      expect(
        stringEDFContent.includes(edfData.railIndicator),
        edfData.railIndicator + `Domestic indicator is included in EDF file`
      );
      //credit card copmany validation in EDF file
      expect(
        stringEDFContent.includes(edfData.creditCardIndicator),
        edfData.creditCardIndicator + `Credit card company is included in EDF file`
      );
      //Base amount charge validation in EDF file
      cy.task('getDataFromCache', 'trainTotalBookingCharge').then((base: any) => {
        const amountRegex = /\$\d+(\.\d{1,2})?/;
        const extractedAmount = base.match(amountRegex)[0].slice(1);
        expect(
          stringEDFContent.includes(extractedAmount),
          extractedAmount + `Base amount charge is included in EDF file`
        );
      });
      //departure date validation in EDF file
      cy.task('getDataFromCache', 'departureLocation').then((departureDLocation: any) => {
        expect(
          stringEDFContent.includes(departureDLocation),
          departureDLocation + `Departure location is included in EDF file`
        );
      });
      //arrival date validation in EDF file
      cy.task('getDataFromCache', 'arrivalLocation').then((arrivalLocation: any) => {
        expect(
          stringEDFContent.includes(arrivalLocation),
          arrivalLocation + `Arrival location is included in EDF file`
        );
      });
    });
  }

  static verifyCardNumber(stringEDFContent: string, body: any) {
    const last4digits = body.creditCard.lastFourDigits;
    const cards: { [index: string]: string } = {
      '0007': edfData.amexSandboxCardNumber,
      '1111': edfData.visaCardNumber,
      '8431': edfData.amexCardNumber
    };
    const paymentCardNumber = cards[last4digits];

    if (paymentCardNumber && stringEDFContent.includes(paymentCardNumber)) {
      cy.log(
        `EDF file payment card number is as expected: ${paymentCardNumber} contains in EDF file`
      );
    } else {
      throw new Error('EDF file payment card number is not as expected');
    }
  }

  static edfSGFileContentValidations() {
    cy.allure().logStep('SG EDF file required validations');
    this.getEdfFile().then((edfContent: any) => {
      const stringEDFContent = String(edfContent);
      const pairs = [
        { start: 0, end: 4, value: edfData.headerStatsWith, msg: 'Header value' },
        { start: 4, end: 10, value: currentDate, msg: 'Created date' },
        {
          start: 10,
          end: 14,
          value: edfData.amexValueForTravelAgent,
          msg: 'Amex value for travel agent'
        },
        {
          start: 25,
          end: 35,
          value: edfData.travelAgentMerchantNumber,
          msg: 'Travel agent merchant number'
        },
        { start: 35, end: 42, value: edfData.sgTravelerName, msg: 'Travel agent name' }
      ];

      pairs.forEach((pair) => {
        const actualValue = edfContent.slice(pair.start, pair.end);
        if (actualValue === pair.value) {
          cy.log(
            'SG EDF file ${pair.msg} is as expected: ${pair.value} actual: ${actualValue}'
          );
        } else {
          throw new Error(
            'SG EDF file ${pair.msg} does not start with: ${pair.value} actual: ${actualValue}'
          );
        }
      });
      expect(
        edfContent.includes(edfData.currency),
        edfData.currency + 'is not included in SG EDF file'
      );
      cy.log(edfData.currency + 'is included in SG EDF file as expected.');

      // Payment card number validation in EDF file
      cy.task('getDataFromCache', 'paymentMethod').then(
        this.verifyCardNumber.bind(null, stringEDFContent)
      );
    });
  }
}
