import clsx from 'clsx';
import React, { useRef } from 'react';
import { useDropzone } from 'react-dropzone';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { toast } from '@/components/toast/Toast';
import { TrashIcon, UploadIcon } from '@/icons';

export type SelectorComponentProps = {
  width: number;
  height: number;
  maxDuration: number;
  getRootProps: ReturnType<typeof useDropzone>['getRootProps'];
  getInputProps: ReturnType<typeof useDropzone>['getInputProps'];
};

interface VideoSelectorProps {
  onVideoSelect: (file: File | null) => void;
  selectedVideo?: File | null;
  width?: number;
  height?: number;
  maxDuration?: number;
  selectorComponent?: React.ComponentType<SelectorComponentProps>;
}

export const VideoSelector = ({
  onVideoSelect,
  selectedVideo,
  width = 200,
  height = 300,
  maxDuration = 11,
  selectorComponent,
}: VideoSelectorProps) => {
  const videoRef = useRef<HTMLVideoElement>(null);

  const { getRootProps, getInputProps } = useDropzone({
    accept: {
      'video/mp4': ['.mp4'],
      'video/quicktime': ['.mov'],
    },
    maxFiles: 1,
    onDrop: async (files) => {
      if (!files?.[0]) return;

      // Check video duration
      const video = document.createElement('video');
      video.preload = 'metadata';

      try {
        const duration = await new Promise<number>((resolve) => {
          video.onloadedmetadata = () => {
            const duration = video.duration;
            URL.revokeObjectURL(video.src);
            resolve(duration);
          };
          video.src = URL.createObjectURL(files[0]);
        });

        if (duration >= maxDuration) {
          toast({
            title: 'Video too long',
            description: `Please upload a video that is ${maxDuration - 1} seconds or shorter`,
            status: 'error',
            duration: 4000,
            isClosable: true,
          });
          onVideoSelect(null);
          return;
        }

        if (duration < 1) {
          toast({
            title: 'Video too short',
            description: 'Please upload a video that is at least 1 second long',
            status: 'error',
            duration: 4000,
            isClosable: true,
          });
          onVideoSelect(null);
          return;
        }

        onVideoSelect(files[0]);
      } catch (error) {
        console.error('Error checking video duration:', error);
        onVideoSelect(null);
      }
    },
  });

  if (selectorComponent) {
    return React.createElement(selectorComponent, {
      getRootProps,
      getInputProps,
      width,
      height,
      maxDuration,
    });
  }

  return (
    <div className='flex shrink-0 flex-col gap-4'>
      {selectedVideo ? (
        <div className='relative'>
          <video
            className='rounded-lg object-cover'
            ref={videoRef}
            src={URL.createObjectURL(selectedVideo)}
            style={{
              width: width,
              height: height,
            }}
            controls
            controlsList='nodownload nofullscreen noremoteplayback'
          />
          <Button
            className='absolute top-1 right-1'
            variant={ButtonVariant.Glass}
            size={ButtonSize.Small}
            shape={ButtonShape.Pill}
            icon={TrashIcon}
            aria-label='Remove video'
            onClick={() => onVideoSelect(null)}
          />
        </div>
      ) : (
        <div
          className={clsx(
            'flex flex-col items-center justify-center gap-4 p-10',
            'cursor-pointer rounded-xl border-4 border-background-primary',
            'bg-background-secondary text-foreground-primary'
          )}
          {...getRootProps()}
          style={{ width, height }}
        >
          <input {...getInputProps()} />
          <UploadIcon className='h-10 w-10' />
          <p className='text-center'>Upload a Video</p>
        </div>
      )}
    </div>
  );
};
