import { expect, FrameLocator, Page } from "@playwright/test";

export class CheckoutPage {
  page: Page;

  constructor(page: Page) {
    this.page = page;
  }

  shippingAddress = {
    email: "playwrightvn@gmail.com",
    countryCode: "CA",
    firstName: "Auto",
    lastName: "Test",
    address1: "2459 Lynden Road",
    phone: "250 555 0199",
    zipcode: "N3L 4A2"
  }

  defaultCardNumber = {
    number: "4578890081868844",
    expDate: "02/2028",
    cvv: "732"
  }

  defaultPaypalAccount = {
    username: "for.test.perifit@gmail.com",
    password: "Testforperifit2024"
  };

  defaultShopPay = {
    account: "for.test.perifit@gmail.com",
    password: "Testforperifit2024"
  }

  xpathSelectCountry = `//select[@name='countryCode']`;
  xpathSelectProvinceOrState = `//select[@id='Select1']`;
  xpathBtnCountinueToShipping = `//div[@class='MV9Am']/descendant::button`;
  xpathBtnCountinueToPayment = `//div[@class='MV9Am']/descendant::button`;
  xpathInputCardNumber = `//input[@placeholder='Card number'] | //input[@placeholder='Número de tarjeta']`;
  xpathInputCardExpDate = `//input[@placeholder='Expiration date (MM / YY)'] | //input[@placeholder='Fecha de vencimiento (MM / AA)']`;
  xpathInputCardCVV = `//input[@placeholder='Security code'] | //input[@placeholder='Código de seguridad']`;
  xpathBtnReviewOrder = `//div[@class='MV9Am']/descendant::button | //button[@id='checkout-pay-button']`;
  xpathHeadingPayment = "//h2[text()='Payment'] | //h2[text()='Kontakt'] | //h2[text()='Pago'] | //h2[text()='Paiement'] | //span[text()=\"Rivedi l'ordine\"] | //span[text()='Bestelling nakijken']"
  xpathBtnPayWithPaypal = "//span[contains(@class, 'paypal-button')]";
  xpathBreadCrumb = "//nav[@aria-label='Breadcrumb'] | //nav[@aria-label='Fil d’Ariane']";
  xpathBtnPayNow = "//span[text()='Pay now'] | //button[@id='checkout-pay-button']";
  xpathShopPayExpress = "//a[@id='shop-pay-button']";
  xpathPayPalExpress = "//paypal-button | //div[@aria-label='PayPal' and @id='buttons-container']";
  xpathCheckboxRememberMe = "//input[contains(@id,'RememberMeCheckbox')]";
  xpathErrorMessage = "//div[text()='Your payment couldn’t be verified. Try again or use a different payment method.'] | //div[text()='There was an issue processing your payment. Try again or use a different payment method.']";
  xpathErrorMessageES = "//div[text()='No se pudo verificar tu pago. Inténtalo de nuevo o utiliza una forma de pago diferente.']"

  // PayPal
  xpathHeaderTextPayPal = "//h1[@id='headerText']";
  xpathUsernamePayPal = "//input[@id='email']";
  xpathPasswordPayPal = "//input[@id='password']";
  xpathBtnLogIn = "//button[@id='btnLogin']";
  xpathChooseAWayToPay = "//div[text()='Choose a way to pay']";
  xpathAddACreditOrPrepaidCard = "//div[text()='Add a credit or prepaid card']";
  xpathCardNumberPayPal = "//input[@id='cardNumber']";
  xpathExpirationDatePayPal = "//input[@id='cardExpiry']";
  xpathCardCVVPayPal = "//input[@id='cardCvv']";
  xpathLogoPayPal = "//p[@class='paypal-logo paypal-logo-monogram']";

  // ShopPay
  xpathIframeShopPayPayment = "//iframe[@id='shop-pay-login-iframe']";
  xpathBtnChangeShopPayPayment = "//button[text()='Change'] | //button[text()='Cambiar']";

  xpathIframePopupShopPayPayment1 = "//iframe[@title='Action required']";
  xpathIframePopupShopPayPayment2 = "//iframe[@id='threedsIframeV2']";
  xpathIframePopupShopPayPayment3 = "//iframe[contains(@id,'cardinal-stepUpIframe')]";
  xpathPurchaseAuthentication = "//div[contains(text(),'Purchase authentication')]";

  async inputEmail(email: string) {
    await this.page.locator(`//input[@id='email']`).fill(email);
  }

  async selectCountry(countryCode: string) {
    await this.page.locator(this.xpathSelectCountry).selectOption({ value: countryCode });
    await this.page.waitForTimeout(1500);
  }

  async inputFirstName(firstName: string) {
    await this.page.locator("(//input[@name='firstName'])[1]").fill(firstName);
  }

  async inputLastName(lastName: string) {
    await this.page.locator("(//input[@name='lastName'])[1]").fill(lastName);
  }

  async inputCompany(company: string) {
    await this.page.locator("(//input[@name='company'])[1]").fill(company);
  }

  async inputAddress1(address1: string) {
    await this.page.locator("(//input[@name='address1'])[1]").fill(address1);
    await this.page.waitForSelector("//h3[text()='Suggestions'] | //h3[text()='Sugerencias'] | //h3[@id='shipping-address1-autocomplete-title']");
    await this.selectOptionAddress1();
  }

  async selectOptionAddress1() {
    await this.page.locator("//li[@id='shipping-address1-option-0']").click();
  }

  async inputAddress2(address2: string) {
    await this.page.locator("(//input[@name='address2'])[1]").fill(address2);
  }

  async inputCity(city: string) {
    await this.page.locator("//input[@id='TextField4']").fill(city);
  }

  async inputZipcode(zipcode: string) {
    await this.page.locator("(//input[@name='postalCode'])[1]").fill(zipcode);
  }

  async inputPhoneNumber(phone: string) {
    await this.page.locator("(//input[@name='phone'])[1]").fill(phone);
  }

  async selectProvinceOrState(value: string) {
    await this.page.locator(this.xpathSelectProvinceOrState).selectOption(value);
  }

  async uncheckRememberMe() {
    const isChecked = await this.page.locator(this.xpathCheckboxRememberMe).isChecked();
    if (isChecked) {
      await this.page.locator(this.xpathCheckboxRememberMe).setChecked(false);
    }
  }

  async fillCheckoutInfo(shippingAddress: {
    email: string,
    countryCode: string,
    firstName: string,
    lastName: string,
    address1: string,
    phone: string,
    zipcode: string
  }) {
    const isMultiplePagesLayout = await this.page.locator(this.xpathBreadCrumb).first().isVisible();
    if (!isMultiplePagesLayout) {
      await this.page.locator("//h2[text()='Shipping method'] | //h2[text()='Métodos de envío'] | //h2[@id='shippingMethod']").scrollIntoViewIfNeeded();
      await this.inputEmail(shippingAddress.email);
      await this.selectCountry(shippingAddress.countryCode);
      await this.inputFirstName(shippingAddress.firstName);
      await this.inputLastName(shippingAddress.lastName);
      await this.inputAddress1(shippingAddress.address1);
      await this.inputPhoneNumber(shippingAddress.phone);
      await this.page.waitForTimeout(2000);
      await this.inputZipcode(shippingAddress.zipcode);
    } else {
      await this.page.locator(this.xpathBtnCountinueToShipping).scrollIntoViewIfNeeded();
      await this.inputEmail(shippingAddress.email);
      await this.selectCountry(shippingAddress.countryCode);
      await this.inputFirstName(shippingAddress.firstName);
      await this.inputLastName(shippingAddress.lastName);
      await this.inputAddress1(shippingAddress.address1);
      await this.inputPhoneNumber(shippingAddress.phone);
      await this.page.waitForTimeout(2000);
      await this.inputZipcode(shippingAddress.zipcode);
      await this.page.locator(this.xpathBtnCountinueToShipping).click();
      await this.page.locator(this.xpathBtnCountinueToPayment).click();
    }
  }

  async checkoutWithStripe(defaultCardNumber = this.defaultCardNumber) {
    await this.page.click("//input[@id='basic-creditCards']");
    const iframeCardNumber = this.page.frameLocator("//iframe[contains(@id, 'card-fields-number')]");
    const iframeExpDate = this.page.frameLocator("//iframe[contains(@id, 'card-fields-expiry')]");
    const iframeCvv = this.page.frameLocator("//iframe[contains(@id, 'card-fields-verification')]");
    await iframeCardNumber.locator(this.xpathInputCardNumber).fill(defaultCardNumber.number);
    await iframeExpDate.locator(this.xpathInputCardExpDate).fill(defaultCardNumber.expDate);
    await iframeCvv.locator(this.xpathInputCardCVV).fill(defaultCardNumber.cvv);
    await this.page.click(this.xpathBtnReviewOrder);
    await this.page.click(this.xpathBtnPayNow);
  }

  async checkoutWithPaypal() {
    const iframePayPal1 = this.page.frameLocator("//iframe[@id='PAY_WITH_PAYPAL-iframe']");

    await this.page.locator("//input[@id='basic-PAYPAL_EXPRESS']").click();

    await this.page.waitForTimeout(5_000);

    const [popup] = await Promise.all([
      this.page.waitForEvent("popup", { timeout: 20_000 }),
      await iframePayPal1.locator("//paypal-button").click()
    ]);
    await popup.waitForLoadState();
    return true;

    // login
    await popup.waitForSelector(this.xpathHeaderTextPayPal);
    await popup.locator("//input[@id='email']").fill(this.defaultPaypalAccount.username);
    await popup.locator("//button[contains(@class,'login-click-next')]").click();
    await popup.waitForTimeout(2000);

    if (await popup.locator(this.xpathLogoPayPal).first().isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathHeaderTextPayPal).isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathPasswordPayPal).isVisible()) {
      return true;
    } else {
      return false;
    }
  }

  async checkoutWithPaypalWithThreeStep() {
    const iframePayPal1 = this.page.frameLocator("//iframe[@id='PAY_WITH_PAYPAL-iframe']");

    await this.page.locator("//input[@id='basic-PAYPAL_EXPRESS']").click();

    await this.page.waitForTimeout(2000);

    await this.page.click(this.xpathBtnReviewOrder);

    const [popup] = await Promise.all([
      this.page.waitForEvent("popup", { timeout: 10000 }),
      await iframePayPal1.locator("//paypal-button").click()
    ]);
    await popup.waitForLoadState();

    return true;
    // login
    await popup.waitForSelector(this.xpathHeaderTextPayPal);
    await popup.locator("//input[@id='email']").fill(this.defaultPaypalAccount.username);
    await popup.locator("//button[contains(@class,'login-click-next')]").click();
    await popup.waitForTimeout(2000);

    if (await popup.locator(this.xpathLogoPayPal).first().isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathHeaderTextPayPal).isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathPasswordPayPal).isVisible()) {
      return true;
    } else {
      return false;
    }

  }

  async checkoutWithPaypalWith1PageLayout() {
    await this.page.locator("//input[@id='basic-PAYPAL_EXPRESS']").click();
    await this.page.waitForTimeout(2000);
    const iframePayPal = this.page.frameLocator("(//iframe[@title='PayPal'])[2]");

    const [popup] = await Promise.all([this.page.waitForEvent("popup", { timeout: 5000 }), await iframePayPal.locator("//div[@aria-label='Pay with PayPal']").click()]);
    await popup.waitForLoadState();

    // login
    await popup.waitForSelector(this.xpathHeaderTextPayPal);
    await popup.locator("//input[@id='email']").fill(this.defaultPaypalAccount.username);
    await popup.locator("//button[contains(@class,'login-click-next')]").click();
    await popup.waitForTimeout(2000);

    if (await popup.locator(this.xpathLogoPayPal).first().isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathHeaderTextPayPal).isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathPasswordPayPal).isVisible()) {
      return true;
    } else {
      return false;
    }
  }

  async checkoutWithShopPay(defaultCardNumber = this.defaultCardNumber) {
    await this.page.click("//span[text()='Credit card'] | //span[text()='Tarjeta de crédito']");
    const iframeCardNumber = this.page.frameLocator("//iframe[contains(@id, 'card-fields-number')]");
    const iframeExpDate = this.page.frameLocator("//iframe[contains(@id, 'card-fields-expiry')]");
    const iframeCvv = this.page.frameLocator("//iframe[contains(@id, 'card-fields-verification')]");
    await iframeCardNumber.locator(this.xpathInputCardNumber).fill(defaultCardNumber.number);
    await iframeExpDate.locator(this.xpathInputCardExpDate).fill(defaultCardNumber.expDate);
    await iframeCvv.locator(this.xpathInputCardCVV).fill(defaultCardNumber.cvv);
    await this.page.waitForSelector(this.xpathBtnReviewOrder);
    await this.page.click(this.xpathBtnReviewOrder);
    await this.page.waitForTimeout(2000);
    await this.page.click(this.xpathBtnPayNow);
    await this.page.waitForTimeout(2_000);
  }

  async checkoutWithShopPayExpress(email: string) {
    await this.page.click(this.xpathShopPayExpress);
    const iframeShopPayPayment = this.page.frameLocator(this.xpathIframeShopPayPayment);
    await iframeShopPayPayment.locator("//input[@id='IdentityEmailForm-input']").fill(this.defaultShopPay.account);
    await iframeShopPayPayment.locator("//button[contains(@class,'button')]").click();
    await this.page.waitForTimeout(7000);
  }

  async checkoutWithPayPalExpress() {
    await this.page.waitForTimeout(5000);
    const iframePayPal = this.page.frameLocator("//iframe[@class='component-frame visible' or @id='PAYPAL_EXPRESS-iframe']").first();

    const [popup] = await Promise.all([
      this.page.waitForEvent("popup", { timeout: 15_000 }),
      iframePayPal.locator(this.xpathPayPalExpress).click({ force: true })
    ]);

    await popup.waitForLoadState();
    // Just verify the popup displayed
    return true;

    // login
    await popup.waitForSelector(this.xpathHeaderTextPayPal);
    await popup.locator("//input[@id='email']").fill(this.defaultPaypalAccount.username);
    await popup.locator("//button[contains(@class,'login-click-next')]").click();
    await popup.waitForTimeout(6000);

    if (await popup.locator(this.xpathLogoPayPal).first().isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathHeaderTextPayPal).isVisible()) {
      return true;
    } else if (await popup.locator(this.xpathPasswordPayPal).isVisible()) {
      return true;
    } else {
      return false;
    }
  }

  /**
  * Validate the existence of the element on DOM, return true or false with timeout
  * @param xpath
  * @param frameParent: in case xpath is in iframe
  * @param timeout
  */
  async checkElementAttached(xpath: string, frameParent?: Page | FrameLocator | null, timeout = 100): Promise<boolean> {
    try {
      const element = frameParent ? frameParent.locator(xpath) : this.page.locator(xpath);
      await expect(element).toBeAttached({ timeout: timeout });
      return true;
    } catch (error) {
      return false;
    }
  }
}