/* eslint-disable max-len */
/// <reference types="cypress" />

// Base widget with STL
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget1Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2OWUxMWYwZDRkMDc0MWMwMjE0OGM4NyJ9.5-TNhGgodbvzb2aF1SxkCeE4NkLDKwWoumrJ_hrnpvA';

// Agreed media widget
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget2Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2OWUxYWQwZDRkMDc0MWMwMjE0YjI1MyJ9.GMIiz4j24XIe46HXpWsA_nlkk9r6kgYtFLDkgXebIOc';

// Exact Medias with minimum 2 products linked
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget3Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2OWUxYzdjZDRkMDc0MWMwMjE0YjhmOSJ9.PyF6VHFPHemcAP_UjEqU_jQ5CntSns_6_vDGTWAK7y0';

// Similar Medias with minimum 2 products linked
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget4Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2OWUyMGY2ZDRkMDc0MWMwMjE0YzM2ZSJ9.ub3jdkztjFcm5OP33j0SJ56ITxulZY21voWBz3kLVPk';

// Widget with english products
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget5Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2YTdiMTFjNzBhYTYwMmVkOTAzYzJkNyJ9.Q6z-hkX2IisqoQGLcWjveMp3aEQzdrWCkzV3hRWRd-E';

// Widget with minimum content not reached
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget6Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2YTdiM2QxNzBhYTYwMmVkOTAzY2ZkZSJ9.Oiy1UBWrwoeyRxDZeiOSMJ0WeQTi_4SmyTPSCbY4MNQ';

// Widget with maximum number of medias
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget7Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2YWI5ZWEzNzBhYTYwMmVkOTA5YjVjOCJ9.SakzCdTppcu1Hpmv0-SsFpLq6a1PaP-KIRRTG9Dhec8';

// Widget with maximum 2 exact products and 2 similar products displayed
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget8Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2YWI5ZjVkNzBhYTYwMmVkOTA5YjhlNiJ9.BqW1tuOtlBnb7jqSrHGdVA_INl-Amw9xkpOfB2_yuYo';

// Widget with 6 videos
// no-dd-sa:typescript-node-security/detected-jwt-token
const widget9Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2YmI2NTJjMzk3M2EyNDNiM2QwMDRkYSJ9.okQ1mdQsnSyyX3WKg8ka8bebOeRMHD2Azdla3YWPloc';

// Widget for carousel layout test
const widget10Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY5ODlmNDEwMTI4NTQ2YjVhODk3NDA5YiJ9.ZG_XdF9q3cRGRit91qtT8cnyM9PEXhHein_hpr7pUc4';

const visitAndLoadWidget = (token: string) => {
  // Load the widget
  cy.visit('http://localhost:3000');

  // Type the widget token
  cy.get('#apiKey').clear().type(token);

  // Click the load button
  cy.get('#load').click();
};

const checkWidgetMediaNb = (mediaCount: number) => {
  // Check if the widget is visible
  cy.get('#widget').should('be.visible');
  cy.get('.adl-wdgt-layout-wall').should('be.visible');

  // There must be 'mediaCount' medias in the widget
  cy.get('.adl-wdgt-layout-wall .adl-wdgt-item .adl-wdgt-thumbnail').should(
    'have.length',
    mediaCount,
  );
};

const clickOnFirstMedia = (shouldDisplayProducts: boolean = false) => {
  // Click on the first media
  cy.get('.adl-wdgt-layout-wall .adl-wdgt-item').first().click();

  // Check if the modal is visible
  cy.get('.adl-wdgt-postviewer').should('be.visible');
  cy.get('.adl-wdgt-postviewer-content').should('be.visible');

  if (shouldDisplayProducts) {
    cy.get('.adl-wdgt-postviewer-details').should('be.visible');
  }
};

const clickOnNbMedia = (position: number, shouldDisplayProducts: boolean = false) => {
  // Click on the indicated media (careful : index is the position)
  cy.get('.adl-wdgt-layout-wall .adl-wdgt-item').eq(position).click();

  cy.get('.adl-wdgt-postviewer').should('be.visible');
  cy.get('.adl-wdgt-postviewer-content').should('be.visible');

  if (shouldDisplayProducts) {
    cy.get('.adl-wdgt-postviewer-details').should('be.visible');
  }
};

const closeModal = () => {
  // Use force:true because the SVG icon child can intercept Cypress's hit-test.
  cy.get('.adl-wdgt-postviewer-close').click({ force: true });

  checkModalDoesNotExists();
};

const checkModalDoesNotExists = () => {
  cy.get('.adl-wdgt-postviewer').should('not.exist');
  cy.get('.adl-wdgt-postviewer-content').should('not.exist');
  cy.get('.adl-wdgt-postviewer-details').should('not.exist');
};

const checkProductDisplay = (shouldExist: boolean) => {
  if (shouldExist) {
    cy.get('.adl-wdgt-postviewer-details').should('exist');
  } else {
    cy.get('.adl-wdgt-postviewer-details').should('not.exist');
  }
};

const checkShopTheLookAvailability = (shouldExist: boolean) => {
  if (shouldExist) {
    cy.get('.adl-wdgt-postviewer-details').contains('div', 'SHOP THE LOOK').should('exist');
  } else {
    cy.get('.adl-wdgt-postviewer-details').contains('div', 'SHOP THE LOOK').should('not.exist');
  }
};

const checkMoreLikeThisAvailability = (shouldExist: boolean) => {
  if (shouldExist) {
    cy.get('.adl-wdgt-postviewer-details').contains('div', 'More like this').should('exist');
  } else {
    cy.get('.adl-wdgt-postviewer-details').contains('div', 'More like this').should('not.exist');
  }
};

const checkProductAvailability = (productName: string, shouldExist: boolean) => {
  if (shouldExist) {
    cy.get('.adl-wdgt-postviewer-details').contains(productName).should('exist');
  } else {
    cy.get('.adl-wdgt-postviewer-details').contains(productName).should('not.exist');
  }
};

const clickNextButton = () => {
  cy.get('.adl-wdgt-arrow-right').click();
};

const clickPreviousButton = () => {
  cy.get('.adl-wdgt-arrow-left').click();
};

const checkLocalization = (text:string) => {
  cy.contains(text).should('exist');
};

// Function to check the maximum number of medias
const checkMaxMedias = (maxCount:number) => {
  cy.get('.adl-wdgt-layout-wall .adl-wdgt-item').should('have.length.lte', maxCount);
};

/** checkProducts function :
 * Usage examples :
 * Min 3 products : checkProductCount(3);
 * Max 5 products : checkProductCount(null, 5);
 * 3 to 5 products : checkProductCount(3, 5);
 * Validate that there are products : checkProductCount();
 * */

// check the existence/count of medias for exact products
const checkExactProducts = (minCount: number | null, maxCount: number | null) => {
  cy.get('.adl-wdgt-postviewer-details').then(($container) => {
    if ($container) {
      const shopThisLookSection = $container.find(':contains("SHOP THE LOOK")');

      if (shopThisLookSection.length > 0) {
        // Get the immediate next sibling div which contains the products
        cy.wrap(shopThisLookSection)
          .parent()
          .next('div')
          .find('.adl-wdgt-postviewer-details-product')
          .then(($products) => {
            const productCount = $products.length;

            if (minCount !== null) {
              expect(productCount).to.be.at.least(minCount);
            }

            if (maxCount !== null) {
              expect(productCount).to.be.at.most(maxCount);
            }
          });
      } else if (minCount === null) {
        // "SHOP THIS LOOK" section not found
        cy.log(
          'SUCCESS: "Shop The Look" section is missing, but no defined minimum of exact medias',
        );
      } else {
        throw new Error(
          'FAIL: "Shop The Look" section is missing and there is a minimum number of exact medias expected.',
        );
      }
    } else {
      throw new Error('FAIL: Unable to find .adl-wdgt-postviewer-details container.');
    }
  });
};

// check the existence/count of medias for similar products
const checkSimilarProducts = (minCount: number | null, maxCount: number | null) => {
  cy.get('.adl-wdgt-postviewer-details').then(($container) => {
    if ($container) {
      const moreLikeThisSection = $container.find(':contains("More like this")');

      if (moreLikeThisSection.length > 0) {
        // Get the immediate next sibling div which contains the products
        cy.wrap(moreLikeThisSection)
          .parent()
          .next('div')
          .find('.adl-wdgt-postviewer-details-product')
          .then(($products) => {
            const productCount = $products.length;

            if (minCount !== null) {
              expect(productCount).to.be.at.least(minCount);
            }

            if (maxCount !== null) {
              expect(productCount).to.be.at.most(maxCount);
            }
          });
      } else if (minCount === null) {
        // "MORE LIKE THIS" section not found
        cy.log(
          'SUCCESS: "More Like This" section is missing, but no defined minimum of exact medias',
        );
      } else {
        throw new Error(
          'FAIL: "More Like This" section is missing and there is a minimum number of exact medias expected.',
        );
      }
    } else {
      throw new Error('FAIL: Unable to find .adl-wdgt-postviewer-details container.');
    }
  });
};

const iterateAndCheckMedia = (
  checkFunction: (minCount: number | null, maxCount: number | null) => void,
  minCount: number | null = null,
  maxCount: number | null = null,
) => {
  cy.get('.adl-wdgt-layout-wall .adl-wdgt-item')
    .its('length')
    .then((totalItems) => {
      if (!totalItems) {
        throw new Error('FAIL: No medias found to iterate over.');
      }

      const visitMedia = (currentIndex: number) => {
        cy.get('body').then(($body) => {
          const hasDetails = $body.find('.adl-wdgt-postviewer-details').length > 0;

          if (!hasDetails) {
            throw new Error('FAIL: Expected .adl-wdgt-postviewer-details to exist.');
          }

          checkFunction(minCount, maxCount);
        });

        if (currentIndex >= totalItems - 1) {
          closeModal();
          return;
        }

        clickNextButton();

        cy.get('.adl-wdgt-postviewer')
          .should('be.visible');

        cy.wait(300);

        cy.get('.adl-wdgt-postviewer-details', { timeout: 10000 })
          .should('exist')
          .then(() => {
            visitMedia(currentIndex + 1);
          });
      };

      cy.get('.adl-wdgt-layout-wall .adl-wdgt-item').first().click();

      cy.get('.adl-wdgt-postviewer').should('be.visible');
      cy.get('.adl-wdgt-postviewer-content').should('be.visible');

      cy.then(() => {
        visitMedia(0);
      });
    });
};

function iterateAndPlayVideos() {
  cy.get('.adl-wdgt-layout-wall .adl-wdgt-item').each((media, index, list) => {
    cy.get('.adl-wdgt-postviewer').should('be.visible');
    cy.get('.adl-wdgt-postviewer-content').should('be.visible');

    // The duration bar only renders while the video is playing — its presence
    // confirms autoplay succeeded.
    cy.get('[role="progressbar"][aria-label="Video progress"]').should('exist');

    // Wait up to 5s for the progress bar to appear (video may load slowly)
    cy.get('[role="progressbar"][aria-label="Video progress"]', { timeout: 5000 })
      .should('exist');

    cy.wait(2500);

    // After playing for a moment the video position must have advanced.
    cy.get('[role="progressbar"][aria-label="Video progress"]')
      .invoke('attr', 'aria-valuenow')
      .then((val) => expect(Number(val)).to.be.greaterThan(0));

    if (index < list.length - 1) {
      clickNextButton();
    }
  });
}

describe('Widget', () => {
  it('Should load and display the widget', () => {
    visitAndLoadWidget(widget1Token);

    checkWidgetMediaNb(32);

    checkModalDoesNotExists();
  });

  it('Should display the modal when clicking on a media', () => {
    visitAndLoadWidget(widget1Token);

    checkModalDoesNotExists();

    clickOnFirstMedia(true);

    checkShopTheLookAvailability(true);

    checkProductAvailability('Cookies', true);

    closeModal();
  });

  it('Should change media when clicking on the arrow buttons', () => {
    visitAndLoadWidget(widget1Token);

    clickOnNbMedia(1, true);

    checkMoreLikeThisAvailability(true);

    checkProductAvailability('MacBook Pro', true);

    clickNextButton();

    checkMoreLikeThisAvailability(true);

    checkProductAvailability('Tote Bag Ice Cream', true);

    checkProductAvailability('Mug AdAlong', false);
    checkProductAvailability('Cookies', false);
    checkProductAvailability('Galette de Rois', false);
    checkProductAvailability('La Felicità', false);
    checkProductAvailability('MacBook Pro', false);

    clickPreviousButton();

    checkMoreLikeThisAvailability(true);

    checkProductAvailability('Galette de Rois', true);
    checkProductAvailability('La Felicità', true);
    checkProductAvailability('MacBook Pro', true);

    checkProductAvailability('Mug AdAlong', false);
    checkProductAvailability('Tote Bag Ice Cream', false);
  });

  it('Should display widget for agreed media only (AGREED)', () => {
    visitAndLoadWidget(widget2Token);

    checkWidgetMediaNb(28);

    clickOnFirstMedia(false);

    // 'Details' component should not exist, since the widget does not display linked products
    checkProductDisplay(false);
  });

  it('Should display the products in English (LOCALIZATION)', () => {
    visitAndLoadWidget(widget5Token);

    checkWidgetMediaNb(8);

    clickOnNbMedia(4, true);

    checkLocalization('Product');
  });

  it('Should display and play videos (VIDEOS)', () => {
    visitAndLoadWidget(widget9Token);
    checkWidgetMediaNb(6);

    cy.get('.adl-wdgt-layout-wall .adl-wdgt-item').first().click();
    iterateAndPlayVideos();
    closeModal();
  });

  it('Should emit minContentNotReached event if minimum content is not met (NUMBER OF UGCS : MIN)', () => {
    visitAndLoadWidget(widget6Token);
    cy.on('minContentNotReached', () => {
      cy.wrap(true).should('be.true');
    });
  });

  it('Should display maximum 12 medias (NUMBER OF UGCS : MAX)', () => {
    visitAndLoadWidget(widget7Token);
    checkMaxMedias(12);
  });

  it('Should display medias with minimum 2 exact products linked in the "SHOP THE LOOK" section (UGC FILTERS : EXACT - MIN)', () => {
    visitAndLoadWidget(widget3Token);
    iterateAndCheckMedia(checkExactProducts, 2, null);
  });

  it('Should display medias with minimum 2 similar products linked in the "MORE LIKE THIS" section (UGC FILTERS : SIMILAR - MIN)', () => {
    visitAndLoadWidget(widget4Token);
    iterateAndCheckMedia(checkSimilarProducts, 2, null);
  });

  it('Should display maximum 2 products in the "SHOP THE LOOK" section (STL DISPLAY : EXACT - MAX)', () => {
    visitAndLoadWidget(widget8Token);
    iterateAndCheckMedia(checkExactProducts, null, 2);
  });

  it('Should display maximum 2 products in the "MORE LIKE THIS" section (STL DISPLAY : SIMILAR - MAX)', () => {
    visitAndLoadWidget(widget8Token);
    iterateAndCheckMedia(checkSimilarProducts, null, 2);
  });

  it('Should not show arrows in mobile mode (carousel)', () => {
    visitAndLoadWidget(widget10Token);
    cy.viewport('iphone-6');
    cy.get('body').then($body => {
      const isCarousel = $body.find('.adl-wdgt-layout-carousel').length > 0;
      if (isCarousel) {
        cy.get('.adl-wdgt-arrow-left').should('not.exist');
        cy.get('.adl-wdgt-arrow-right').should('not.exist');
      } else {
        cy.log('Carousel layout not present, skipping arrow check.');
      }
    });
  });
});
