'use client'

import { SectionLabel, Text } from '@/components/ui'
import { motion, useMotionValue, useMotionValueEvent, useScroll, useSpring, useTransform } from 'motion/react'
import Image from 'next/image'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import type { PaymentJourneyCard } from '@/types/home'
import { useIsRtl } from '@/lib/use-is-rtl'

interface PaymentJourneyProps {
  subTitle: string
  title: string
  description: string
  cards: PaymentJourneyCard[]
}

const CARD_SCROLL_HEIGHT_VH = 90
const DESKTOP_HEADER_HEIGHT_PX = 70
const WHEEL_INTENT_THRESHOLD = 50
const CARD_SNAP_LOCK_MS = 850
const STICKY_EDGE_TOLERANCE_PX = 2

export const PaymentJourney = ({ subTitle, title, description, cards }: PaymentJourneyProps) => {
  const isRtl = useIsRtl()
  const isRtlMotion = useMotionValue(isRtl ? 1 : 0)

  useEffect(() => {
    isRtlMotion.set(isRtl ? 1 : 0)
  }, [isRtl, isRtlMotion])

  const sectionRef = useRef<HTMLElement>(null)
  const sliderRef = useRef<HTMLDivElement>(null)
  const cardRefs = useRef<Array<HTMLElement | null>>([])
  const activeIndexRef = useRef(0)
  const isSnapLockedRef = useRef(false)
  const wheelDeltaRef = useRef(0)
  const touchStartRef = useRef<{ x: number; y: number } | null>(null)
  const unlockTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const [activeIndex, setActiveIndex] = useState(0)
  const cardCount = Math.max(cards.length, 1)
  const desktopSectionHeight = `${cardCount * CARD_SCROLL_HEIGHT_VH}vh`
  const { scrollYProgress } = useScroll({
    target: sectionRef,
    offset: [`start ${DESKTOP_HEADER_HEIGHT_PX}px`, 'end end'],
  })
  const trackXProgress = useTransform(scrollYProgress, [0, 1], [0, -(cardCount - 1) * 100])
  const smoothTrackXProgress = useSpring(trackXProgress, {
    stiffness: 115,
    damping: 32,
    mass: 0.35,
  })
  const trackX = useTransform(
    [smoothTrackXProgress, isRtlMotion],
    ([value, rtl]: number[]) => `${rtl ? -value : value}vw`
  )

  useMotionValueEvent(scrollYProgress, 'change', (latest) => {
    if (cards.length <= 1 || isSnapLockedRef.current) return

    const nextIndex = Math.min(cards.length - 1, Math.max(0, Math.round(latest * (cards.length - 1))))
    if (nextIndex !== activeIndexRef.current) {
      activeIndexRef.current = nextIndex
      setActiveIndex(nextIndex)
    }
  })

  const releaseSnapLock = useCallback(() => {
    if (unlockTimerRef.current) {
      clearTimeout(unlockTimerRef.current)
      unlockTimerRef.current = null
    }

    isSnapLockedRef.current = false
    wheelDeltaRef.current = 0
  }, [])

  const scheduleSnapUnlock = useCallback(() => {
    if (unlockTimerRef.current) {
      clearTimeout(unlockTimerRef.current)
    }

    unlockTimerRef.current = setTimeout(releaseSnapLock, CARD_SNAP_LOCK_MS)
  }, [releaseSnapLock])

  const scrollToCard = useCallback((index: number) => {
    const section = sectionRef.current
    if (!section || cardCount <= 1) return

    const sectionTop = window.scrollY + section.getBoundingClientRect().top
    const scrollStart = sectionTop - DESKTOP_HEADER_HEIGHT_PX
    const scrollEnd = sectionTop + section.offsetHeight - window.innerHeight
    const scrollRange = Math.max(scrollEnd - scrollStart, 0)

    window.scrollTo({
      top: scrollStart + scrollRange * (index / (cardCount - 1)),
      behavior: 'smooth',
    })
  }, [cardCount])

  const handleDesktopWheel = useCallback((event: React.WheelEvent<HTMLDivElement>) => {
    if (cards.length <= 1) return

    const section = sectionRef.current
    if (!section) return

    const sectionBounds = section.getBoundingClientRect()
    const isPinned =
      sectionBounds.top <= DESKTOP_HEADER_HEIGHT_PX + STICKY_EDGE_TOLERANCE_PX &&
      sectionBounds.bottom >= window.innerHeight - STICKY_EDGE_TOLERANCE_PX

    if (!isPinned || event.deltaY === 0) return

    const currentIndex = activeIndexRef.current
    const wheelDirection = event.deltaY > 0 ? 1 : -1
    const targetIndex = Math.min(cards.length - 1, Math.max(0, currentIndex + wheelDirection))

    if (targetIndex === currentIndex) {
      wheelDeltaRef.current = 0
      return
    }

    event.preventDefault()

    if (isSnapLockedRef.current) return

    wheelDeltaRef.current += event.deltaY
    if (Math.abs(wheelDeltaRef.current) < WHEEL_INTENT_THRESHOLD) return

    const snapDirection = wheelDeltaRef.current > 0 ? 1 : -1
    const nextIndex = Math.min(cards.length - 1, Math.max(0, currentIndex + snapDirection))
    wheelDeltaRef.current = 0

    if (nextIndex === currentIndex) return

    isSnapLockedRef.current = true
    activeIndexRef.current = nextIndex
    setActiveIndex(nextIndex)
    scrollToCard(nextIndex)
    scheduleSnapUnlock()
  }, [cards.length, scheduleSnapUnlock, scrollToCard])

  const handleTouchStart = useCallback((event: React.TouchEvent<HTMLDivElement>) => {
    const touch = event.touches[0]
    touchStartRef.current = touch ? { x: touch.clientX, y: touch.clientY } : null
  }, [])

  const handleTouchMove = useCallback((event: React.TouchEvent<HTMLDivElement>) => {
    if (cards.length <= 1) return

    const section = sectionRef.current
    const start = touchStartRef.current
    const touch = event.touches[0]
    if (!section || !start || !touch) return

    const sectionBounds = section.getBoundingClientRect()
    const isPinned =
      sectionBounds.top <= DESKTOP_HEADER_HEIGHT_PX + STICKY_EDGE_TOLERANCE_PX &&
      sectionBounds.bottom >= window.innerHeight - STICKY_EDGE_TOLERANCE_PX

    if (!isPinned) return

    const deltaX = start.x - touch.clientX
    const deltaY = start.y - touch.clientY
    if (Math.abs(deltaY) < 36 || Math.abs(deltaY) < Math.abs(deltaX)) return

    const currentIndex = activeIndexRef.current
    const targetIndex = Math.min(cards.length - 1, Math.max(0, currentIndex + (deltaY > 0 ? 1 : -1)))

    if (targetIndex === currentIndex) {
      touchStartRef.current = { x: touch.clientX, y: touch.clientY }
      return
    }

    event.preventDefault()

    if (isSnapLockedRef.current) return

    isSnapLockedRef.current = true
    activeIndexRef.current = targetIndex
    setActiveIndex(targetIndex)
    scrollToCard(targetIndex)
    scheduleSnapUnlock()
    touchStartRef.current = { x: touch.clientX, y: touch.clientY }
  }, [cards.length, scheduleSnapUnlock, scrollToCard])

  const handleTouchEnd = useCallback(() => {
    touchStartRef.current = null
  }, [])

  useEffect(() => releaseSnapLock, [releaseSnapLock])

  return (
    <div className='stack'>
      <section
        id='payment-journey'
        className='bg-[#F5F5F5] py-20 md:py-24 xl:py-[150px]'
      >
        <div className='shrink-0 pxcontainer'>
          <SectionLabel
            textclass='mx-auto max-w-[50rem] text-center'
            className='flex-center flex-col space-y-5'
            label={subTitle}
            title={<span dangerouslySetInnerHTML={{ __html: title.replace('<span>', '<span class="gradient-text-green">') }} />}
            description={description}
          />
        </div>

        {/* Mobile: vertical stack */}
        <div className='flex flex-col gap-10 lg:hidden pxcontainer stack'>
          {cards.map((item, index) => (
            <div key={item.made_for_everyday_payments_background__text} className='flex flex-col sm:items-center'>
              <div className='relative z-20'>
                <h2 className='text-center relative uppercase text-[#101E10]/10 -z-10 top-5 text-[50px] font-extrabold leading-[64px]'>{item.made_for_everyday_payments_background__text}</h2>
                <div className='flex gap-10 flex-col'>
                  <div className='flex-center'>
                    <Image src={item.made_for_everyday_payments_image} alt='Paysey mobile wallet application' width={250} height={500} className='w-[250px]' priority={index === 0} />
                  </div>
                  <div className='space-y-3'>
                    <Text size='h3' fontWeight={600} textKey={item.made_for_everyday_payments_title} />
                    <Text size='normal' textKey={item.made_for_everyday_payments_description} />
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>

        {/* Desktop: vertical scroll drives the sticky horizontal journey */}
        <section ref={sectionRef} className='relative hidden lg:block' style={{ height: desktopSectionHeight }}>
          <div
            className='sticky top-[70px] overflow-hidden'
            style={{ height: `calc(100vh - ${DESKTOP_HEADER_HEIGHT_PX}px)` }}
            onWheel={handleDesktopWheel}
            onTouchStart={handleTouchStart}
            onTouchMove={handleTouchMove}
            onTouchEnd={handleTouchEnd}
            onTouchCancel={handleTouchEnd}
          >
            <motion.div
              ref={sliderRef}
              style={{ x: trackX }}
              className='flex h-full w-max will-change-transform'
            >
              {cards.map((item, index) => (
                <motion.article
                  key={item.made_for_everyday_payments_background__text}
                  ref={(element) => { cardRefs.current[index] = element }}
                  aria-hidden={activeIndex !== index}
                  initial={{ opacity: index === 0 ? 1 : 0.5, scale: index === 0 ? 1 : 0.965 }}
                  animate={activeIndex === index ? { opacity: 1, scale: 1 } : { opacity: 0.5, scale: 0.965 }}
                  transition={{ type: 'spring', stiffness: 80, mass: 0.5 }}
                  className='relative flex h-full w-screen shrink-0 items-center justify-center overflow-hidden px-[7vw] lg:px-[11vw]'
                >
                  <div className='relative z-20 mx-auto flex h-[90%] max-h-[90vh] w-full items-center justify-center'>
                   
                    <div className='flex-center h-full pt-[clamp(2.5rem,8vh,6rem)]'>
                      <div className='relative z-20 w-[clamp(210px,24vw,350px)] max-h-[78vh]'>
                        <Text
                          size='h3'
                          fontWeight={600}
                          className={isRtl
                            ? 'absolute right-[calc(-1*clamp(18rem,23vw,22rem))] xl:right-[calc(-1*clamp(15rem,23vw,22rem))] top-1/2 -z-10 max-w-[18rem] -translate-y-1/2 xl:max-w-[20rem]'
                            : 'absolute left-[calc(-1*clamp(18rem,23vw,22rem))]  xl:left-[calc(-1*clamp(15rem,23vw,22rem))] top-1/2 -z-10 max-w-[18rem] -translate-y-1/2 xl:max-w-[20rem]'}
                          textKey={item.made_for_everyday_payments_title}
                        />
                    <div className='relative'>
                          <Image
                          src={item.made_for_everyday_payments_image}
                          alt='Paysey mobile wallet application'
                          width={350}
                          height={700}
                          className='h-auto max-h-[78vh] w-full object-contain'
                          sizes='(min-width: 1280px) 350px, (min-width: 1024px) 26vw, 250px'
                          priority={index === 0}
                        />
                         <h2 className='pointer-events-none absolute left-1/2 -top-20 -z-10 w-max -translate-x-1/2 whitespace-nowrap uppercase text-[#101E10]/8 text-[clamp(72px,7vw,120px)] font-extrabold leading-none'>{item.made_for_everyday_payments_background__text}</h2>
                    </div>
                        <Text
                          size='normal'
                          className={isRtl
                            ? 'absolute left-[calc(-1*clamp(20rem,26vw,25rem))] xl:left-[calc(-1*clamp(15rem,26vw,25rem))] bottom-[clamp(4rem,16vh,10rem)] max-w-[18rem] xl:max-w-[20rem]'
                            : 'absolute right-[calc(-1*clamp(20rem,26vw,25rem))] xl:right-[calc(-1*clamp(15rem,26vw,25rem))] bottom-[clamp(4rem,16vh,10rem)] max-w-[18rem] xl:max-w-[20rem]'}
                          textKey={item.made_for_everyday_payments_description}
                        />
                      </div>
                    </div>
                  </div>
                </motion.article>
              ))}
            </motion.div>
          </div>
        </section>
      </section>
    </div>
  )
}
