import { useState, useEffect, useCallback, useContext, RefObject } from 'react';
import { IProduct } from '../types';
import { StoreContext } from '../services/store';
import { productCarouselGap } from '../components/consts';

interface UseProductCarouselProps {
  products: IProduct[];
  containerRef: RefObject<HTMLDivElement>;
  scrollContainerRef: RefObject<HTMLDivElement>;
}

interface CarouselState {
  scrollPosition: number;
  canScrollPrev: boolean;
  canScrollNext: boolean;
  enableTransition: boolean;
}

interface CarouselActions {
  scrollPrev: () => void;
  scrollNext: () => void;
  getScrollPosition: () => number;
  getItemWidth: (index: number) => number;
}

export const useProductCarousel = ({
  products,
  scrollContainerRef,
}: UseProductCarouselProps): CarouselState & CarouselActions => {
  const context = useContext(StoreContext);
  const [scrollPosition, setScrollPosition] = useState<number>(0);
  const [canScrollPrev, setCanScrollPrev] = useState(false);
  const [canScrollNext, setCanScrollNext] = useState(false);
  const [enableTransition, setEnableTransition] = useState(true);

  const getItemWidth = useCallback(
    (index: number): number => {
      const imageWidth = context.getProductImageWidth(products[index]?.id) || 0;
      const containerWidth = scrollContainerRef.current?.clientWidth || 400;

      if (imageWidth > 0) {
        return imageWidth;
      }

      // Fallback to responsive width when no image width available
      return Math.min(containerWidth * 0.4, 200);
    },
    [context, products, scrollContainerRef],
  );

  // Calculate total width of all items including gaps
  const getTotalWidth = useCallback((): number => {
    let totalWidth = 0;
    for (let i = 0; i < products.length; i++) {
      totalWidth += getItemWidth(i);
      if (i < products.length - 1) {
        totalWidth += productCarouselGap;
      }
    }
    return totalWidth;
  }, [products, getItemWidth]);

  // Get the width of items that fit in the current view
  const getViewWidth = useCallback((): number => {
    return scrollContainerRef.current?.clientWidth || 0;
  }, [scrollContainerRef]);

  // Find the next scroll position for true view-based scrolling
  const getNextScrollPosition = useCallback(
    (direction: 'prev' | 'next'): number => {
      const viewWidth = getViewWidth();
      const totalWidth = getTotalWidth();

      if (direction === 'prev') {
        // For previous: scroll back by exactly one view width
        const newPosition = Math.max(0, scrollPosition - viewWidth);
        return newPosition;
      } else {
        // For next: find the first item that's partially visible (cut off)
        // Then make that item the first fully visible item in the next view
        let accumulatedWidth = 0;
        const currentViewEnd = scrollPosition + viewWidth;

        for (let i = 0; i < products.length; i++) {
          const itemWidth = getItemWidth(i);
          const itemStart = accumulatedWidth;
          const itemEnd = accumulatedWidth + itemWidth;

          if (itemStart < currentViewEnd && itemEnd > currentViewEnd) {
            const maxScroll = Math.max(0, totalWidth - viewWidth);
            return Math.min(itemStart, maxScroll);
          }

          if (itemStart >= currentViewEnd) {
            const maxScroll = Math.max(0, totalWidth - viewWidth);
            return Math.min(itemStart, maxScroll);
          }

          accumulatedWidth += itemWidth + productCarouselGap;
        }

        // If no partially visible item found, scroll by view width
        const maxScroll = Math.max(0, totalWidth - viewWidth);
        return Math.min(scrollPosition + viewWidth, maxScroll);
      }
    },
    [scrollPosition, getViewWidth, getTotalWidth, products, getItemWidth],
  );

  const scrollPrev = useCallback(() => {
    const newPosition = getNextScrollPosition('prev');
    setScrollPosition(newPosition);
  }, [getNextScrollPosition]);

  const scrollNext = useCallback(() => {
    const newPosition = getNextScrollPosition('next');
    setScrollPosition(newPosition);
  }, [getNextScrollPosition]);

  const getScrollPosition = useCallback(() => {
    return scrollPosition;
  }, [scrollPosition]);

  useEffect(() => {
    const viewWidth = getViewWidth();
    const totalWidth = getTotalWidth();

    setCanScrollPrev(scrollPosition > 0);
    setCanScrollNext(scrollPosition < totalWidth - viewWidth);
  }, [scrollPosition, products.length, getViewWidth, getTotalWidth]);

  // Reset when products change
  useEffect(() => {
    setEnableTransition(false);
    setScrollPosition(0);

    const timer = setTimeout(() => setEnableTransition(true), 50);
    return () => clearTimeout(timer);
  }, [products]);

  return {
    scrollPosition,
    canScrollPrev,
    canScrollNext,
    enableTransition,
    scrollPrev,
    scrollNext,
    getScrollPosition,
    getItemWidth,
  };
};
