import { AUTH_TOKEN } from '../commands';
import { stagingUsers } from '@fixtures/staging-users';
import { CommerceClient } from '@support-commerce/commerce_clients';
import { localizationData } from '@fixtures/commerce/localization_data';
import { ledgerRequests } from '@fixtures/commerce/ledger_requests';

const { us_domestic_sabre_user } = stagingUsers;
const userCredentials = Cypress.env('newUser').NEW_USER_PASSWORD;
const english = localizationData.english;

Cypress.Commands.add(
  'assignChargeableEntityToFeeModel',
  (companyUUID: string, feeModelName: string) => {
    if (AUTH_TOKEN) {
      postChargeableEntity(companyUUID, feeModelName);
    }
  }
);

Cypress.Commands.add('getChargeableEntityToFeeModel', (companyUUID: string) => {
  if (AUTH_TOKEN) {
    getChargeableEntitybyUuid(companyUUID);
  }
});

Cypress.Commands.add('getChargeableEntity', (feeModelName: string) => {
  if (AUTH_TOKEN) {
    getChargeableEntity(feeModelName);
  }
});

export const postChargeableEntity = (companyUUID: string, feeModelName: string) => {
  const requestBody = {
    companyUuid: `${companyUUID}`,
    currency: 'USD',
    chargeType: 'CHARGE',
    statementCurrency: 'USD',
    description: 'FEE MODEL CURRENCY USD'
  };
  return cy
    .request({
      method: 'POST',
      url: `/api/fees/v1/chargeableEntity`,
      headers: {
        Authorization: AUTH_TOKEN
      },
      body: requestBody,
      retryOnStatusCodeFailure: true
    })
    .then(({ body, status }) => {
      expect(status, 'Created chargeable entity').to.equal(200);
      return getFeeModal(body.uuid, feeModelName);
    });
};

const getFeeModal = (chargeableEntityUUID: string, feeModelName: string) => {
  cy.request({
    method: 'GET',
    url: `/api/fees/v1/feeModel`,
    headers: {
      Authorization: AUTH_TOKEN
    },
    retryOnStatusCodeFailure: true
  }).then(({ body, status }) => {
    expect(status, 'Got fee models').to.equal(200);
    for (const feeModel of body) {
      if (feeModel.name === feeModelName) {
        assignToFeeModel(chargeableEntityUUID, feeModel.uuid);
      }
    }
  });
};

const getChargeableEntity = (feeModelName: string) => {
  cy.request({
    method: 'GET',
    url: `/api/fees/v1/feeModel`,
    headers: {
      Authorization: AUTH_TOKEN
    },
    retryOnStatusCodeFailure: true
  }).then(({ body, status }) => {
    expect(status, 'Got fee models').to.equal(200);
    for (const feeModel of body) {
      if (feeModel.name === feeModelName) {
        return { uuid: feeModel.uuid, name: feeModel.name };
      }
    }
  });
};

export const getChargeableEntitybyUuid = (companyUUID: string) => {
  return cy
    .request({
      method: 'GET',
      url: `/api/fees/v1/feeModel/${companyUUID}`,
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true
    })
    .then(({ body, status }) => {
      expect(status, 'Created chargeable entity').to.equal(200);
      return body;
    });
};

const assignToFeeModel = (chargeableEntityUUID: string, feeModelUUID: string) => {
  const yesterdayDate = new Date();
  yesterdayDate.setDate(yesterdayDate.getDate() - 1);
  const requestBody = {
    feeModelUuid: `${feeModelUUID}`,
    chargeableEntityUuid: `${chargeableEntityUUID}`,
    startDate: yesterdayDate
  };
  cy.request({
    method: 'POST',
    url: `/api/fees/v1/feeModel/assign`,
    headers: {
      Authorization: AUTH_TOKEN
    },
    body: requestBody,
    retryOnStatusCodeFailure: true
  }).then(({ body, status }) => {
    expect(status, 'Assigned chargeable entity to fee model').to.equal(200);
    return body;
  });
};

Cypress.Commands.add(
  'insertBookingDataInLedger',
  (
    bookingUuid: string,
    bookingId: string,
    totalAmount: number,
    baseAmount: number,
    totalTaxAmount: number,
    ticketType: string,
    ticketNumber: string,
    providerType: string,
    inventoryType: string,
    exchangeAmount: any,
    metaData: any,
    coupons: any
  ) => {
    cy.loginWithAuthToken({
      email: us_domestic_sabre_user.email,
      password: userCredentials,
      isSA: true
    }).then(() =>
      insertBookingDataInLedger(
        bookingUuid,
        bookingId,
        totalAmount,
        baseAmount,
        totalTaxAmount,
        ticketType,
        ticketNumber,
        providerType,
        inventoryType,
        exchangeAmount,
        metaData,
        coupons
      )
    );
  }
);

Cypress.Commands.add(
  'insertTransactionInLedger',
  (
    bookingUuid: string,
    bookingId: string,
    amount: number,
    taxAmount: any,
    ticketType: string,
    ticketNumber: string,
    providerType: string,
    inventoryType: string,
    metadata: any,
    currency: string,
    coupon: any
  ) => {
    cy.loginWithAuthToken({
      email: us_domestic_sabre_user.email,
      password: userCredentials,
      isSA: true
    }).then(() =>
      insertTransactionInLedger(
        bookingUuid,
        bookingId,
        amount,
        taxAmount,
        ticketType,
        ticketNumber,
        providerType,
        inventoryType,
        metadata,
        currency,
        coupon
      )
    );
  }
);

Cypress.Commands.add('bookingDataInLedger', (requestBody: any) => {
  cy.loginWithAuthToken({
    email: us_domestic_sabre_user.email,
    password: userCredentials,
    isSA: true
  }).then(() => bookingDataInLedger(requestBody));
});

Cypress.Commands.add('archiveByBookingUUID', (bookingUuid: string) => {
  cy.loginWithAuthToken({
    email: us_domestic_sabre_user.email,
    password: userCredentials,
    isSA: true
  }).then(() => archiveByBookingUUID(bookingUuid));
});

Cypress.Commands.add('clearAllByBookingUuid', (bookingUuid: string) => {
  cy.loginWithAuthToken({
    email: us_domestic_sabre_user.email,
    password: userCredentials,
    isSA: true
  }).then(() => clearAllByBookingUuid(bookingUuid));
});

function insertBookingDataInLedger(
  bookingUuid: string,
  bookingId: string,
  totalAmount: number,
  baseAmount: number,
  totalTaxAmount: number,
  ticketType: string,
  ticketNumber: string,
  providerType: string,
  inventoryType: string,
  exchangeAmount: any,
  metaData: any,
  coupons: any
) {
  if (AUTH_TOKEN) {
    cy.request({
      method: 'POST',
      url: CommerceClient.insertFlightBooking,
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true,
      body: {
        bookingUuid: bookingUuid,
        bookingId: bookingId,
        ticketNumber: ticketNumber,
        totalAmount: totalAmount,
        totalCurrency: 'USD',
        baseAmount: baseAmount,
        baseCurrency: 'USD',
        totalTaxAmount: totalTaxAmount,
        taxCurrency: 'USD',
        providerType: providerType,
        inventoryType: inventoryType,
        ticketType: ticketType,
        supplierTotal: null,
        supplierBase: null,
        equivalentAmount: null,
        equivalentCurrency: null,
        supplierEquivalent: null,
        collectedAmount: exchangeAmount,
        collectedCurrency: null,
        supplierCollected: null,
        comissionAmount: null,
        comissionPercentage_rate: null,
        comissionCurrency: null,
        supplierCommission: null,
        supplierTotalTax: null,
        associatedTicketNumber: null,
        travelerFirstName: 'Zack',
        travelerLastName: 'Marks',
        issueDate: null,
        fareCalculation: null,
        ticketJson: null,
        ticketTaxes: null,
        coupons: coupons,
        ticketPaymentMethods: null,
        priceIncludesTax: null,
        currencyConversionRates: null,
        additionalCharges: null,
        metadata: metaData
      }
    }).then(({ status }) => {
      expect(status, 'Inserting booking data in Ledger').to.equal(200);
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}

function archiveByBookingUUID(bookingUuid: string) {
  if (AUTH_TOKEN) {
    cy.request({
      method: 'GET',
      url: CommerceClient.archiveTransaction.replace('{bookingUuid}', bookingUuid),
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true
    }).then(({ status }) => {
      expect(status, 'archive transaction By BookingUUID').to.equal(200);
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}

function clearAllByBookingUuid(bookingUuid: string) {
  if (AUTH_TOKEN) {
    // Clear All on Invoice
    cy.request({
      method: 'POST',
      url: CommerceClient.invoiceClearAll.replace('{bookingUuid}', bookingUuid),
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true
    }).then(({ status }) => {
      expect(status, 'Successfully cleared all BookingUUID on Invoice').to.equal(200);
    });
    // Clear All on Ledger
    cy.request({
      method: 'POST',
      url: CommerceClient.ledgerClearAll.replace('{bookingUuid}', bookingUuid),
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true
    }).then(({ status }) => {
      expect(status, 'Successfully cleared all BookingUUID on Ledger').to.equal(200);
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}

function insertTransactionInLedger(
  bookingUuid: string,
  bookingId: string,
  amount: number,
  taxAmount: any,
  type: string,
  ticketNumber: string,
  providerType: string,
  inventoryType: string,
  metadata: any,
  currency: string,
  coupon: any
) {
  if (AUTH_TOKEN) {
    cy.request({
      method: 'POST',
      url: CommerceClient.createTransaction,
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true,
      body: {
        bookingUuid: bookingUuid,
        bookingId: bookingId,
        transactionId: ticketNumber,
        transactionDate: '2024-05-10T16:22:07.875Z',
        totalCharge: {
          amount: amount,
          currency: currency
        },
        baseCharge: {
          amount: amount,
          currency: currency
        },
        total_tax: {
          amount: 0.0,
          currency: currency
        },
        providerType: providerType,
        inventoryType: inventoryType,
        type: type,
        supplierTotal: null,
        supplierBase: null,
        equivalentAmount: null,
        equivalentCurrency: null,
        supplierEquivalent: null,
        collectedAmount: null,
        collectedCurrency: null,
        supplierCollected: null,
        comissionAmount: null,
        comissionPercentage_rate: null,
        comissionCurrency: null,
        supplierCommission: null,
        supplierTotalTax: null,
        associatedTicketNumber: null,
        travelerFirstName: null,
        travelerLastName: null,
        issueDate: null,
        fareCalculation: null,
        ticketJson: null,
        ticketTaxes: null,
        coupons: null,
        ticketPaymentMethods: null,
        priceIncludesTax: null,
        currencyConversionRates: null,
        additionalCharges: null,
        metadata: metadata,
        payment_methods: [
          {
            masked_card_number: 'XXXXXXXXXXXX1111',
            expiry_date: '0125',
            card_type: 'VISA',
            payment_method_type: 'CC',
            payment_method_nickname: null,
            charged_amount: amount,
            charged_amount_currency: 'USD'
          }
        ],
        taxes: taxAmount
      }
    }).then(({ status }) => {
      expect(status, 'Inserting transaction data in Ledger').to.equal(200);
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}
function bookingDataInLedger(requestBody: any) {
  if (AUTH_TOKEN) {
    cy.request({
      method: 'POST',
      url: CommerceClient.insertFlightBooking,
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true,
      body: requestBody
    }).then(({ status }) => {
      expect(status, 'booking data in Ledger').to.equal(200);
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}
