import { useEffect, useReducer, useRef, useState } from 'react';
import { MiniTitle } from '../../ui/MiniTitle';
import { useWindowWidth } from '../../hooks/useWindowWidth';
import { Title } from '../../ui/Title';
import { useSwipeable } from 'react-swipeable';
import { ArrowLeftIcon } from '../icons/ArrowLeftIcon';
import { ArrowRightIcon } from '../icons/ArrowRightIcon';
import { PauseIcon } from '../icons/PauseIcon';
import { PlayIcon } from '../icons/PlayIcon';
import useStateRef from 'react-usestateref';

enum Media {
  video,
  img,
}

interface IProject<TMedia extends Media> {
  src: TMedia extends Media.img ? string : string[];
  title: string;
  tags: string[];
  media?: TMedia;
}

export function Projects() {
  return (
    <div
      id="projects"
      className="lg:py-[70px] lg:px-10 py-14 sm:px-6 px-4 overflow-hidden"
    >
      <Title className="2xl:mb-[77px] lg:mb-14 mb-6">
        <span className="text-gradient">Большой опыт в работе</span> с
        промышленными предприятиями и учебными заведениями
      </Title>
      <MiniTitle text="реализованные проекты" />
      <Slider
        projects={[
          {
            src: 'src/assets/projects/loader.png',
            tags: ['Симулятор'],
            title: 'Симулятор погрузчика',
            media: Media.img,
          },
          {
            src: [
              'src/assets/projects/operator.mp4',
              'src/assets/projects/operator.png',
            ],
            tags: ['Симулятор', 'VR-приложение'],
            title: 'Обучение работе с системой водоочистки',
            media: Media.video,
          } as IProject<Media.video>,
          {
            src: 'src/assets/projects/plane.png',
            tags: ['Симулятор', 'VR-приложение'],
            title: 'L 410 NG Aircraft',
            media: Media.img,
          },
          {
            src: 'src/assets/projects/hangar.png',
            tags: ['Симулятор', 'VR-приложение'],
            title: 'Сборка-разборка вертолётного двигателя',
            media: Media.img,
          },
          {
            src: 'src/assets/projects/trains.png',
            tags: ['Симулятор', 'VR-приложение'],
            title: 'Тренажер РЖД: ЭП2Д, Иволга, ЭП20, ТЭ33А, ТЭМ2',
            media: Media.img,
          },
          {
            src: 'src/assets/projects/laboratory.png',
            tags: ['Симулятор', 'VR-приложение'],
            title: 'Учебная лаборатория определения жирности молока',
            media: Media.img,
          },
          {
            src: 'src/assets/projects/train_big.jpg',
            tags: ['Симулятор'],
            title: 'Симулятор машиниста',
            media: Media.img,
          },
        ]}
      />
    </div>
  );
}

function Project<T extends Media>({ src, title, tags, media }: IProject<T>) {
  const [buffering, setBuffering] = useState(true);
  const [playing, setPlaying, playingRef] = useStateRef(false);

  const videoRef = useRef<HTMLVideoElement>(null);

  useEffect(() => console.log(buffering), [buffering]);
  useEffect(() => console.log(playingRef), [playingRef]);
  useEffect(() => console.log(playing), [playing]);

  return (
    <div className="bg-[#3D425C] bg-opacity-50 rounded-2xl aspect-[624/462] lg:min-w-[39vw] sm:min-w-[67vw] min-w-[calc(100vw-32px)] lg:translate-x-[calc(15.5vw-32px)] flex flex-col relative">
      {media === Media.img ? (
        <div
          className="bg-cover bg-center bg-no-repeat min-h-[340px] flex-1 rounded-t-2xl"
          style={{ backgroundImage: `url(${src})` }}
        />
      ) : (
        <div
          className="flex-1 rounded-t-2xl overflow-hidden relative flex justify-center items-center group bg-cover bg-center bg-no-repeat"
          style={{ backgroundImage: `url(${src[1]})` }}
        >
          <video
            src={src[0]}
            ref={videoRef}
            muted
            loop
            className="rounded-t-2xl object-cover aspect-[495/340]"
            onPlaying={() => setBuffering(false)}
            onWaiting={() => setBuffering(true)}
          />
          <button
            onClick={() => {
              if (playingRef.current) {
                videoRef.current?.pause();
                setPlaying(false);
              } else {
                videoRef.current?.play();
                setPlaying(true);
              }
            }}
            className={
              'absolute p-4 rounded-full border border-white group-hover:block ' +
              (!buffering && playing ? 'hidden' : 'block')
            }
          >
            {!buffering && playing ? (
              <PauseIcon className="w-4 h-4" />
            ) : (
              <PlayIcon className="w-4 h-4" />
            )}
          </button>
          {buffering && <div className="rounded-t-2xl absolute" />}
        </div>
      )}
      <div className="p-5 flex flex-col justify-between gap-3">
        <h4 className="font-medium h4">{title}</h4>
        <div className="flex gap-2">
          {tags.map(tag => (
            <p
              key={tag}
              className="opacity-80 font-medium rounded-3xl sm:py-3 py-2 px-4 border border-[#798FFF] m-text"
            >
              {tag}
            </p>
          ))}
        </div>
      </div>
    </div>
  );
}

function Slider({ projects }: { projects: IProject<Media>[] }) {
  const width = useWindowWidth();
  const baseOffset =
    width >= 1024 ? width * 0.39 : width >= 640 ? width * 0.67 : width - 20;
  const [sliderOffset, setSliderOffset] = useState(-baseOffset);
  const [slide, setSlide] = useState(0);
  const [isAnimating, setIsAnimating] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  const [order, dispatch] = useReducer(
    (state: typeof projects, action: string) => {
      switch (action) {
        case 'prev':
          setSliderOffset(prev => prev - baseOffset);
          return [state[state.length - 5], ...state.slice(0, -1)];
        case 'next':
          setSliderOffset(prev => prev + baseOffset);
          return [...state.slice(1), state[4]];
        default:
          return state;
      }
    },
    [
      projects[projects.length - 2],
      projects[projects.length - 1],
      ...projects,
      projects[0],
      projects[1],
    ],
  );

  const handlers = useSwipeable({
    onSwipedLeft: () => {
      if (!isAnimating) {
        setIsAnimating(true);
        setSlide(prev => (prev === order.length - 5 ? 0 : prev + 1));
        dispatch('next');
      }
    },
    onSwipedRight: () => {
      if (!isAnimating) {
        setIsAnimating(true);
        setSlide(prev => (prev === 0 ? order.length - 5 : prev - 1));
        dispatch('prev');
      }
    },
    trackMouse: true,
    preventScrollOnSwipe: true,
    touchEventOptions: { passive: false },
  });

  useEffect(() => {
    setSliderOffset(-baseOffset * 2);
  }, [order, baseOffset, slide]);

  useEffect(() => {
    const refValue = ref.current;
    refValue?.addEventListener('transitionend', () => {
      setIsAnimating(false);
    });
    return () =>
      refValue?.removeEventListener('transitionend', () =>
        setIsAnimating(false),
      );
  }, [sliderOffset, order, slide]);

  return (
    <div className="flex flex-col lg:mt-4 sm:mt-3 mt-2">
      <div {...handlers}>
        <div
          ref={ref}
          className="flex sm:gap-4 gap-2 overflow-visible relative mb-[18px] -mr-10 select-none"
          style={{
            transition: `${sliderOffset === -baseOffset || sliderOffset === -baseOffset * 3 ? 0 : 0.5}s`,
            transform: `translateX(${sliderOffset}px)`,
          }}
        >
          {order.map((project, index) => (
            <Project key={index} {...project} />
          ))}
        </div>
      </div>
      <div className="flex items-center gap-4 lg:w-[clamp(720px,100vw-465px,1135px)] 2xl:w-[70.9vw] w-full self-start lg:ml-[15.5vw]">
        <button
          onClick={() => {
            if (!isAnimating) {
              setIsAnimating(true);
              setSlide(prev => (prev === 0 ? order.length - 5 : prev - 1));
              dispatch('prev');
            }
          }}
          className="max-sm:hidden outline-none"
        >
          <ArrowLeftIcon />
        </button>
        <div className="h-1 bg-[#3D425C] w-full">
          <div
            className="bg-[#ffffff] h-1 duration-500"
            style={{ width: `${((slide + 1) / projects.length) * 100}%` }}
          />
        </div>
        <button
          onClick={() => {
            if (!isAnimating) {
              setIsAnimating(true);
              setSlide(prev => (prev === order.length - 5 ? 0 : prev + 1));
              dispatch('next');
            }
          }}
          className="max-sm:hidden outline-none"
        >
          <ArrowRightIcon />
        </button>
      </div>
    </div>
  );
}
