import { AmplitudeEvents, GrowthAmplitudeEvents } from './amplitude-events';
import { Timeouts } from '@utility-lib/index';
import Chainable = Cypress.Chainable;

const cashbackSelectors = {
  cashbackPill: '[data-testid="cashbackEntryPointPill"]',
  cashbackPillText:
    '[data-testid="cashbackEntryPointPill"] [data-testid="home-pill-text"]',
  rewardsPill: '[data-testid="rewardsSubtab"]',
  rewardsEducation: '[data-testid="rewards-education"]',
  cashbackBalancePage: '[data-testid="ta-cashback-balance"]',
  cashbackBalancePageInfo: '[data-testid="ta-cashback"]',
  cashbackBalancePageHowToEarn: '[data-testid="ta-cashback__how-to-earn"]',
  cashbackBalanceRedeemCashbackButton:
    '[data-testid="redeemCashbackButton"] > .ta-button-v2',
  cashbackBalanceHeadingAmount:
    '.ta-cashback-balance__heading__balance__redeemable-balance span',
  cashbackActivitySelector: '.ta-select',
  cashbackBarChart: '.ta-cashback-bar-chart',
  cashbackHistory: '.ta-cashback-history',
  cashbackActivitySelectRedeemedOption:
    '.popover-content :nth-child(2) > .ta-select-option',
  cashbackBalanceRedeemCashbackModal: '[data-testid="cashbackRedeemModal"]',
  cashbackBalanceRedeemCashbackModalCancel:
    '[data-testid="cashbackRedeemCancel"] > .ta-button-v2',
  cashbackRedeemAmountInput: '[data-testid="cashbackRedeemAmountInput"]',
  cashbackRedeemCheckbox: '[data-testid="cashbackRedeemCheckbox"]',
  cashbackRedeemDoRedeem: '[data-testid="cashbackRedeemButton"]',
  cashbackBalanceViewActivityModal: '[data-testid="cashbackActivityModal"]',
  cashbackBalanceViewActivityModalClose:
    '[data-testid="cashbackActivityModal"] .dialogue-close',
  cashbackAmazonRedemptionConfirmation:
    '.ta-amazon-redemption-confirmation__confetti-lottie',
  viewCashbackActivityButton: '[data-testid="viewCashbackActivityButton"]',

  cashbackBannerTitle: '[data-testid="cashbackBannerTitle"]',
  cashbackBannerCta: '[data-testid="cashbackBannerCta"]',
  spendMetricCashback: `[data-testid="spend-performance-metric-CASHBACK"]`,
  spendMetricCashbackCta: `[data-testid="spend-performance-metric-CASHBACK"] .ta-button-v2`,
  growthStatusCard: '[data-testid="growthStatusCard"]',
  growthStatusCardCashback: '[data-testid="state-card-CASHBACK"]'
};

export class CashbackPages {
  private static readonly REDEEM_VALUE: number = 0.01;
  private static readonly EXPECTED_REDEEM_VALUE_IN_CARD = `$0.01`;

  static verifyHomePageShownWithCashback(): void {
    cy.allure().logStep('Verify go to home page for cashback');
    cy.get(cashbackSelectors.cashbackPill).should('exist');
    cy.get(cashbackSelectors.rewardsPill).should('not.exist');
    cy.get(cashbackSelectors.rewardsEducation).should('not.exist');
  }

  static verifyHomePageShownWithCashbackForRouge(): void {
    cy.allure().logStep('Verify go to home page for cashback lead/rouge user');
    cy.get(cashbackSelectors.cashbackPill).should('not.exist');
    cy.get(cashbackSelectors.growthStatusCard).should('exist');
    cy.get(cashbackSelectors.growthStatusCardCashback).should('exist');
  }

  static clickOnCashbackPill(): void {
    cy.allure().logStep('click on cashback pill');
    cy.get(cashbackSelectors.cashbackPill).click();
  }

  static checkCashbackPillAmount(greaterThanZero: boolean): void {
    cy.allure().logStep('verify cashback pill has cashback amount');
    cy.get(cashbackSelectors.cashbackPillText).should(($el) => {
      const text = $el.text();
      const amount = parseFloat(text.match(/\d+.?\d*/)?.[0] || '');

      expect(text).to.include('$');
      expect(text).to.include('USD');
      // Check if the amount is greater than zero or equal to zero
      if (greaterThanZero) {
        expect(amount).to.be.gt(0);
      } else {
        expect(amount).to.be.eq(0);
      }
    });
  }

  static navigateToAdminDashboard(): void {
    cy.allure().logStep('Verify Admin dashboard page is loaded');
    cy.visit('app/admin2/en/dashboard');
    cy.url().should('include', '/dashboard');
  }

  static verifyAdminDashboard(): void {
    cy.get(cashbackSelectors.cashbackBannerTitle).should('exist');
    cy.get(cashbackSelectors.spendMetricCashback).should('exist');
    cy.get(cashbackSelectors.spendMetricCashbackCta).click();
  }

  static verifyCashbackBalancePageShown(): void {
    cy.allure().logStep('click cashback balance shown');
    AmplitudeEvents.addExpectedAmplitudeEvents(GrowthAmplitudeEvents.CASHBACK_PAGE_VIEW);
    cy.get(cashbackSelectors.cashbackBalancePage).should('exist');
  }

  static verifyEmptyStateForNewUser(): void {
    cy.allure().logStep('verify empty state for new user');
    cy.get(cashbackSelectors.cashbackBarChart).should('not.exist');
    cy.get(cashbackSelectors.cashbackHistory).should('not.exist');
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackButton).should('be.disabled');
    this.getHeadingValue().then((value) => {
      expect(value).to.equal(0);
    });
  }

  static verifyCashbackBalancePageFunctionality(): void {
    cy.allure().logStep(
      'verifying cashback balance page redeem button and activity modals'
    );
    cy.get(cashbackSelectors.cashbackBalancePageInfo).should('exist');
    cy.get(cashbackSelectors.cashbackBalancePageHowToEarn).should('exist');
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackModal).should('not.exist');
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackButton).click();
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackModal).should('exist');
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackModalCancel).click();
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackModal).should('not.exist');

    cy.get(cashbackSelectors.cashbackActivitySelector).click();
    cy.wait(Timeouts.SHORT_TIMEOUT_1_SEC.timeout);
    cy.get(cashbackSelectors.cashbackActivitySelectRedeemedOption).click();
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    cy.get(cashbackSelectors.viewCashbackActivityButton).click();
    cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
    cy.get(cashbackSelectors.cashbackBalanceViewActivityModal).should('exist');
    cy.get(cashbackSelectors.cashbackBalanceViewActivityModalClose).click();
    cy.get(cashbackSelectors.cashbackBalanceViewActivityModal).should('not.exist');
  }

  private static getHeadingValue(): Chainable<number> {
    return cy
      .get(cashbackSelectors.cashbackBalanceHeadingAmount)
      .invoke('text')
      .then((text) => {
        const value = parseFloat(text.trim().replace(/[^0-9.-]+/g, '')).toFixed(2);
        return Number(value);
      });
  }

  static fillRedeemCardBy001(): void {
    cy.get(cashbackSelectors.cashbackRedeemAmountInput).should('be.visible');
    cy.get(cashbackSelectors.cashbackRedeemAmountInput).click();
    cy.get(cashbackSelectors.cashbackRedeemAmountInput).clear();
    cy.get(cashbackSelectors.cashbackRedeemAmountInput).type('1');
    cy.get(cashbackSelectors.cashbackRedeemAmountInput)
      .invoke('val')
      .then((inputValue) => {
        const WHITESPACE_REGEX = /\s/g;
        const cleanInputValue = inputValue?.toString().replace(WHITESPACE_REGEX, '');
        if (cleanInputValue === this.EXPECTED_REDEEM_VALUE_IN_CARD) {
          cy.get(cashbackSelectors.cashbackRedeemCheckbox).click();
          cy.get(cashbackSelectors.cashbackRedeemDoRedeem).click();
          cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
          cy.get(cashbackSelectors.cashbackAmazonRedemptionConfirmation).click();
          cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
        } else {
          cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackModalCancel).click();
        }
      });
  }

  static doRedeemCashbackAndVerify(): void {
    cy.allure().logStep('verifying cashback redeem of 0.01$');
    let startValue: number;
    this.getHeadingValue().then((value) => {
      startValue = value;
    });
    cy.get(cashbackSelectors.cashbackBalanceRedeemCashbackButton).click();
    this.fillRedeemCardBy001();

    this.getHeadingValue().then((endValue) => {
      // to fixed is needed because small values calculations in javascript are not precise
      const startMinusRedeemValue = ((startValue || 0) - this.REDEEM_VALUE).toFixed(2);
      const expectedValue = Number(startMinusRedeemValue);
      expect(endValue).to.be.eq(expectedValue);
    });
  }
}
