describe('homepage hero', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders the header navigation', () => {
    cy.get('header.site-header').within(() => {
      cy.contains('Torah Media').should('be.visible')
      cy.contains('About').should('be.visible')
      cy.contains('Donate').should('be.visible')
      cy.contains('a', 'Contact').should('not.exist')
    })
  })

  it('links the navbar Donate item to Causematch', () => {
    const donateHref = 'https://causematch.com/pilzno_donate'

    cy.contains('header.site-header a', 'Donate')
      .should('be.visible')
      .and('have.attr', 'href', donateHref)
      .and('have.attr', 'target', '_blank')
      .and('have.attr', 'rel', 'noopener')
  })

  it('opens the Torah Media page from the header navigation', () => {
    cy.contains('header.site-header a', 'Torah Media').click()

    cy.location('pathname').should('eq', '/media')
    cy.get('header.site-header').within(() => {
      cy.contains('Torah Media').should('be.visible')
      cy.contains('About').should('be.visible')
      cy.contains('Donate').should('be.visible')
      cy.contains('a', 'Contact').should('not.exist')
    })
    cy.contains('h1', 'Torah Media').should('be.visible')
  })

  it('renders the hero headline with italic emphasis', () => {
    cy.get('[data-cy="hero"]').within(() => {
      cy.contains('upgrade our lives').should('be.visible')
      cy.contains('em', 'healthy').should('be.visible')
      cy.contains('em', 'integrated').should('be.visible')
      cy.contains('em', 'balanced').should('be.visible')
      cy.contains('Torah existence').should('be.visible')
      cy.contains('Rabbi Yehoshua Gerzi').should('be.visible')
    })
  })

  it('renders the rabbi portrait image', () => {
    cy.get('[data-cy="hero-portrait"]')
      .should('be.visible')
      .and('have.attr', 'alt')
      .and('match', /Rabbi Yehoshua Gerzi/i)
  })

  it('lets the rabbi portrait rise above the circular frame', () => {
    cy.get<HTMLImageElement>('[data-cy="hero-portrait"]').then(
      (portraitElements) => {
        const portraitImage = portraitElements[0]
        const frameElement = portraitImage.parentElement

        if (frameElement === null) {
          throw new Error('Portrait frame is missing')
        }

        const frameStyle = getComputedStyle(frameElement)

        expect(frameStyle.overflowX).to.equal('visible')
        expect(frameStyle.overflowY).to.equal('visible')
        expect(portraitImage.getBoundingClientRect().top).to.be.lessThan(
          frameElement.getBoundingClientRect().top,
        )
      },
    )
  })

  it('extends the circular background to the portrait base edges', () => {
    cy.get<HTMLImageElement>('[data-cy="hero-portrait"]').then(
      (portraitElements) => {
        const portraitImage = portraitElements[0]
        const frameElement = portraitImage.parentElement

        if (frameElement === null) {
          throw new Error('Portrait frame is missing')
        }

        const portraitBounds = portraitImage.getBoundingClientRect()
        const frameBounds = frameElement.getBoundingClientRect()
        const backgroundStyle = getComputedStyle(frameElement, '::before')
        const backgroundWidth = Number.parseFloat(backgroundStyle.width)
        const backgroundLeft =
          frameBounds.left + (frameBounds.width - backgroundWidth) / 2
        const backgroundRight = backgroundLeft + backgroundWidth

        expect(backgroundStyle.content).to.not.equal('none')
        expect(backgroundWidth).to.be.closeTo(portraitBounds.width, 1)
        expect(backgroundLeft).to.be.closeTo(portraitBounds.left, 1)
        expect(backgroundRight).to.be.closeTo(portraitBounds.right, 1)
      },
    )
  })
})

describe('homepage discover path section', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders the heading and body copy', () => {
    cy.get('[data-cy="discover-path"]').within(() => {
      cy.contains('h2', 'Discover a Path to a Holistically Engaged Life')
        .should('be.visible')
      cy.contains('Rabbi Yehoshua Gerzi has dedicated his life')
        .should('be.visible')
      cy.contains('Healthy, Integrated and Balanced Torah Living')
        .should('be.visible')
      cy.contains('Ramat Beit Shemesh').should('be.visible')
      cy.contains('Pilzno Institute of Higher Learning').should('be.visible')
    })
  })
})

describe('homepage core teachings grid', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders the heading and six teaching tiles', () => {
    cy.get('[data-cy="core-teachings"]').within(() => {
      cy.contains('h2', 'Baderech HaAvodah').should('be.visible')
      cy.contains('Core Teachings').should('be.visible')
      cy.contains('1) Introduction').should('be.visible')
      cy.contains('2) Foundations').should('be.visible')
      cy.contains('3) Divine Plan').should('be.visible')
      cy.contains('4) Architecture of the Soul').should('be.visible')
      cy.contains('5) Arba Yesodot').should('be.visible')
      cy.contains('6) Fluid Integration').should('be.visible')
    })
  })
})

describe('homepage unique voice section', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders heading body and cta button', () => {
    cy.get('[data-cy="unique-voice"]').within(() => {
      cy.contains('h2', 'A Unique Voice for the Generation')
        .should('be.visible')
      cy.contains('wholly unique and much needed perspective')
        .should('be.visible')
      cy.contains('practically engaged positivity').should('be.visible')
      cy.contains('button', /Learn about Rabbi Gerzi.s Approach/)
        .should('be.visible')
    })
  })
})

describe('homepage testimonials carousel', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders the heading and the active testimonial', () => {
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.contains('h2', 'What People Are Saying').should('be.visible')
      cy.get('[data-cy="testimonial-active"]').within(() => {
        cy.contains('Nathaniel M').should('be.visible')
        cy.contains('best Jewish day schools').should('be.visible')
      })
    })
  })

  it('shows faded half-card previews beside the active testimonial', () => {
    cy.viewport(1200, 800)
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-active"]').as('activeCard')
      cy.get('[data-cy="testimonial-previous-preview"]').as(
        'previousPreview',
      )
      cy.get('[data-cy="testimonial-next-preview"]').as('nextPreview')
      cy.get('[data-cy="testimonials-stage"]').as('testimonialStage')
    })

    cy.get('@activeCard').should('be.visible')
    cy.get('@previousPreview').should('be.visible')
    cy.get('@nextPreview').should('be.visible')

    cy.get('@activeCard').then((activeCardElements) => {
      const activeOpacity = Number(
        getComputedStyle(activeCardElements[0]).opacity,
      )

      cy.get('@previousPreview').then((previousPreviewElements) => {
        const previousPreview = previousPreviewElements[0]
        const previousOpacity = Number(
          getComputedStyle(previousPreview).opacity,
        )

        cy.wrap(previousOpacity).should('be.lessThan', activeOpacity)
      })

      cy.get('@nextPreview').then((nextPreviewElements) => {
        const nextPreview = nextPreviewElements[0]
        const nextOpacity = Number(getComputedStyle(nextPreview).opacity)

        cy.wrap(nextOpacity).should('be.lessThan', activeOpacity)
      })
    })

    cy.get('@testimonialStage').then((testimonialStageElements) => {
      const stageBounds = testimonialStageElements[0].getBoundingClientRect()

      cy.get('@previousPreview').then((previousPreviewElements) => {
        const previousBounds =
          previousPreviewElements[0].getBoundingClientRect()
        const previousVisibleWidth = previousBounds.right - stageBounds.left

        cy.wrap(previousVisibleWidth).should(
          'be.closeTo',
          previousBounds.width / 2,
          1,
        )
      })

      cy.get('@nextPreview').then((nextPreviewElements) => {
        const nextBounds = nextPreviewElements[0].getBoundingClientRect()
        const nextVisibleWidth = stageBounds.right - nextBounds.left

        cy.wrap(nextVisibleWidth).should(
          'be.closeTo',
          nextBounds.width / 2,
          1,
        )
      })
    })
  })

  it('keeps desktop cards equal sized and separated', () => {
    const expectedCardGap = 24
    const expectedControlsGap = 12

    cy.viewport(1200, 800)
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-active"]').as('activeCard')
      cy.get('[data-cy="testimonial-previous-preview"]').as(
        'previousPreview',
      )
      cy.get('[data-cy="testimonial-next-preview"]').as('nextPreview')
      cy.get('[data-cy="testimonial-prev"]')
        .parent()
        .as('testimonialControls')
    })

    cy.get('@activeCard').then((activeCardElements) => {
      const activeBounds = activeCardElements[0].getBoundingClientRect()

      cy.get('@previousPreview').then((previousPreviewElements) => {
        const previousBounds =
          previousPreviewElements[0].getBoundingClientRect()
        const previousGap = activeBounds.left - previousBounds.right

        cy.wrap(previousBounds.height).should(
          'be.closeTo',
          activeBounds.height,
          1,
        )
        cy.wrap(previousGap).should('be.closeTo', expectedCardGap, 1)
      })

      cy.get('@nextPreview').then((nextPreviewElements) => {
        const nextBounds = nextPreviewElements[0].getBoundingClientRect()
        const nextGap = nextBounds.left - activeBounds.right

        cy.wrap(nextBounds.height).should(
          'be.closeTo',
          activeBounds.height,
          1,
        )
        cy.wrap(nextGap).should('be.closeTo', expectedCardGap, 1)
      })

      cy.get('@testimonialControls').then((testimonialControlsElements) => {
        const controlsBounds =
          testimonialControlsElements[0].getBoundingClientRect()
        const controlsGap = controlsBounds.top - activeBounds.bottom

        cy.wrap(controlsGap).should(
          'be.closeTo',
          expectedControlsGap,
          1,
        )
      })
    })
  })

  it('rounds the outer corners of clipped preview cards', () => {
    cy.viewport(1200, 800)
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonials-stage"]').as('testimonialStage')
      cy.get('[data-cy="testimonial-active"]').as('activeCard')
    })

    cy.get('@activeCard').then((activeCardElements) => {
      const activeCardStyle = getComputedStyle(activeCardElements[0])

      cy.get('@testimonialStage').then((testimonialStageElements) => {
        const testimonialStageStyle = getComputedStyle(
          testimonialStageElements[0],
        )

        expect(testimonialStageStyle.borderTopLeftRadius).to.equal(
          activeCardStyle.borderTopLeftRadius,
        )
        expect(testimonialStageStyle.borderTopRightRadius).to.equal(
          activeCardStyle.borderTopRightRadius,
        )
        expect(testimonialStageStyle.borderBottomLeftRadius).to.equal(
          activeCardStyle.borderBottomLeftRadius,
        )
        expect(testimonialStageStyle.borderBottomRightRadius).to.equal(
          activeCardStyle.borderBottomRightRadius,
        )
      })
    })
  })

  it('brings entering side previews in from the clicked direction', () => {
    const transitionSampleDelay = 100
    const transitionSettleDelay = 1100

    cy.viewport(1200, 800)
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-prev"]').click()
      cy.get('[data-cy="testimonial-previous-preview"]').as(
        'enteringPreviousPreview',
      )
    })

    cy.wait(transitionSampleDelay)
    cy.get('@enteringPreviousPreview').then((previousPreviewElements) => {
      const earlyPreviousLeft =
        previousPreviewElements[0].getBoundingClientRect().left

      cy.wait(transitionSettleDelay)
      cy.get('@enteringPreviousPreview').then((finalPreviewElements) => {
        const finalPreviousLeft =
          finalPreviewElements[0].getBoundingClientRect().left

        expect(earlyPreviousLeft).to.be.lessThan(finalPreviousLeft)
      })
    })

    cy.visit('/')
    cy.viewport(1200, 800)
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-next"]').click()
      cy.get('[data-cy="testimonial-next-preview"]').as(
        'enteringNextPreview',
      )
    })

    cy.wait(transitionSampleDelay)
    cy.get('@enteringNextPreview').then((nextPreviewElements) => {
      const earlyNextLeft =
        nextPreviewElements[0].getBoundingClientRect().left

      cy.wait(transitionSettleDelay)
      cy.get('@enteringNextPreview').then((finalPreviewElements) => {
        const finalNextLeft =
          finalPreviewElements[0].getBoundingClientRect().left

        expect(earlyNextLeft).to.be.greaterThan(finalNextLeft)
      })
    })
  })

  it('hides side previews on narrow screens', () => {
    cy.viewport(390, 800)
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-active"]').should('be.visible')
      cy.get('[data-cy="testimonial-previous-preview"]')
        .should('not.be.visible')
      cy.get('[data-cy="testimonial-next-preview"]').should('not.be.visible')
    })
  })

  it('advances to the next testimonial when next is clicked', () => {
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-active"]')
        .should('contain.text', 'Nathaniel M')
      cy.get('[data-cy="testimonial-next"]').click()
      cy.get('[data-cy="testimonial-active"]')
        .should('not.contain.text', 'Nathaniel M')
    })
  })

  it('goes back to the previous testimonial when prev is clicked', () => {
    cy.get('[data-cy="testimonials"]').within(() => {
      cy.get('[data-cy="testimonial-next"]').click()
      cy.get('[data-cy="testimonial-prev"]').click()
      cy.get('[data-cy="testimonial-active"]')
        .should('contain.text', 'Nathaniel M')
    })
  })
})

describe('homepage sponsor strip', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders the heading and all seven partner logos in a carousel', () => {
    cy.get('[data-cy="sponsors"]').within(() => {
      cy.contains('h2', 'Organizations Rabbi Gerzi has Worked With')
        .should('be.visible')
      const expectedAlts = [
        'SHARE',
        'U of Israel',
        'Mayberg Foundation',
        'JLE UK',
        'Yeshivat Reishit',
        'Aish HaTorah',
        'Yeshivat Lev HaTorah',
      ]
      cy.get('[data-cy="sponsor-logo"]').should('have.length', 7)
      expectedAlts.forEach((altText) => {
        cy.get(`[data-cy="sponsor-logo"][alt="${altText}"]`)
          .should('have.attr', 'src')
      })
      cy.get('[data-cy="sponsor-carousel"]').should('be.visible')
      cy.get('[data-cy="sponsor-logo-duplicate"]')
        .should('have.length', 7)
      cy.get('[data-cy="sponsor-logo-duplicate"][alt=""]')
        .should('have.length', 7)
      cy.get('[data-cy="sponsor-logo-group-duplicate"]')
        .should('have.attr', 'aria-hidden', 'true')
    })
  })

  it('centers the carousel with side buffers and edge fades', () => {
    cy.viewport(1200, 900)
    cy.get('[data-cy="sponsors"]').within(() => {
      cy.get('[data-cy="sponsor-carousel"]').then((carouselElements) => {
        const carouselElement = carouselElements[0]
        const sponsorInnerElement = carouselElement.parentElement

        if (sponsorInnerElement === null) {
          throw new Error('Sponsor inner element is missing')
        }

        const carouselBounds = carouselElement.getBoundingClientRect()
        const sponsorInnerBounds =
          sponsorInnerElement.getBoundingClientRect()
        const leftBuffer = carouselBounds.left - sponsorInnerBounds.left
        const rightBuffer = sponsorInnerBounds.right - carouselBounds.right
        const carouselRatio = carouselBounds.width / sponsorInnerBounds.width
        const carouselStyle = getComputedStyle(carouselElement)
        const maskImage =
          carouselStyle.maskImage || carouselStyle.webkitMaskImage

        expect(carouselRatio).to.be.closeTo(0.85, 0.02)
        expect(leftBuffer).to.be.closeTo(rightBuffer, 1)
        expect(maskImage).to.contain('50px')
      })
    })
  })

  it('uses the faster carousel timing', () => {
    cy.get('[data-cy="sponsor-track"]').then((trackElements) => {
      const trackStyle = getComputedStyle(trackElements[0])

      expect(trackStyle.animationDuration).to.equal('20s')
    })
  })

  it('scrolls the sponsor logos from right to left', () => {
    cy.get('[data-cy="sponsor-track"]').then((trackElements) => {
      const startingLeft = trackElements[0].getBoundingClientRect().left

      cy.wait(750)
      cy.get('[data-cy="sponsor-track"]').then((laterTrackElements) => {
        const laterLeft =
          laterTrackElements[0].getBoundingClientRect().left

        expect(startingLeft).to.be.greaterThan(laterLeft)
      })
    })
  })
})

describe('homepage projects grid', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders the heading and four project cards', () => {
    cy.get('[data-cy="projects"]').within(() => {
      cy.contains('h2', 'Projects').should('be.visible')
      cy.get('[data-cy="project-card"]').should('have.length', 4)
      cy.contains('h3', 'Chaburot').should('be.visible')
      cy.contains('group learning sessions').should('be.visible')
      cy.contains('h3', 'Pilzno Work Inspired').should('be.visible')
      cy.contains('healthy relationship to work').should('be.visible')
      cy.contains('h3', 'Shul').should('be.visible')
      cy.contains('Pilzno Beis Dovid').should('be.visible')
      cy.contains('h3', 'New Building').should('be.visible')
      cy.contains('Beit Shemesh municipality').should('be.visible')
    })
  })

  it('uses background images for each project card', () => {
    const expectedProjectImages = [
      '/assets/projects/chaburot.webp',
      '/assets/projects/pilzno-work-inspired.webp',
      '/assets/projects/shul.webp',
      '/assets/projects/new-building.webp',
    ]

    cy.get('[data-cy="project-card"]').should('have.length', 4)
    expectedProjectImages.forEach((expectedProjectImage, projectIndex) => {
      cy.get('[data-cy="project-card"]')
        .eq(projectIndex)
        .then((projectCardElements) => {
          const projectCardStyle = getComputedStyle(projectCardElements[0])

          expect(projectCardStyle.backgroundImage).to.contain(
            expectedProjectImage,
          )
        })
    })
  })
})

describe('homepage start your journey ctas', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('renders both journey CTAs with their headings and bodies', () => {
    cy.get('[data-cy="journey"]').within(() => {
      cy.contains('h2', 'Start Your Journey').should('be.visible')
      cy.get('[data-cy="journey-media"]').within(() => {
        cy.contains('Access').should('be.visible')
        cy.contains('Torah Media').should('be.visible')
        cy.contains('wealth of video, audio and written content')
          .should('be.visible')
      })
      cy.get('[data-cy="journey-baderech"]').within(() => {
        cy.contains('Explore').should('be.visible')
        cy.contains('Baderech HaAvodah').should('be.visible')
        cy.contains('transformative principles').should('be.visible')
      })
    })
  })
})

describe('homepage get involved and footer', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('does not render the newsletter signup section', () => {
    cy.get('[data-cy="get-involved"]').should('not.exist')
    cy.contains('Subscribe for updates as we release new content')
      .should('not.exist')
  })

  it('renders the footer with links and copyright', () => {
    cy.get('[data-cy="footer"]').within(() => {
      cy.contains('Torah Media').should('be.visible')
      cy.contains('About').should('be.visible')
      cy.contains('Donate').should('be.visible')
      cy.contains('a', 'Contact').should('not.exist')
      cy.contains(/Rabbi Gerzi 2025/).should('be.visible')
    })
  })

  it('links the footer Donate item to Causematch', () => {
    const donateHref = 'https://causematch.com/pilzno_donate'

    cy.contains('[data-cy="footer"] a', 'Donate')
      .should('be.visible')
      .and('have.attr', 'href', donateHref)
      .and('have.attr', 'target', '_blank')
      .and('have.attr', 'rel', 'noopener')
  })

  it('links footer social icons to the contact social pages', () => {
    const expectedSocialLinks = [
      {
        label: 'YouTube',
        href: 'https://www.youtube.com/@rabbigerzi',
      },
      {
        label: 'Spotify',
        href:
          'https://open.spotify.com/show/' +
          '49H1X9A7KZWAnnIbcoQXQR?si=6253691f23be44ad',
      },
    ]

    cy.get('[data-cy="footer"]').within(() => {
      expectedSocialLinks.forEach((expectedSocialLink) => {
        cy.get(`a[aria-label="${expectedSocialLink.label}"]`)
          .should('be.visible')
          .and('have.attr', 'href', expectedSocialLink.href)
          .and('have.attr', 'target', '_blank')
          .and('have.attr', 'rel', 'noopener')
      })
    })
  })

  it('navigates footer links without reloading the app', () => {
    const footerNavigationMarker = 'client-navigation'

    cy.window().then((applicationWindow) => {
      const markedWindow = applicationWindow as Window & {
        footerNavigationMarker?: string
      }

      markedWindow.footerNavigationMarker = footerNavigationMarker
    })

    cy.contains('[data-cy="footer"] a', 'About').click()

    cy.location('pathname').should('eq', '/about')
    cy.window().then((applicationWindow) => {
      const markedWindow = applicationWindow as Window & {
        footerNavigationMarker?: string
      }

      expect(markedWindow.footerNavigationMarker).to.equal(
        footerNavigationMarker,
      )
    })
    cy.contains('h1', 'About Rabbi Gerzi').should('be.visible')
  })
})
