import clsx from 'clsx';
import React, { useCallback, useEffect, useRef, useState } from 'react';

import Trimmer from '../timeline/Trimmer';

const formatTime = (timestamp: number): string => {
  const seconds = Math.floor(timestamp / 1000);
  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = seconds % 60;
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
};

interface ThumbnailSelectorProps {
  videoUrl: string;
  videoDuration: number;
  thumbnailTimestamp: number;
  onThumbnailTimestampChange: (timestamp: number) => void;
  className?: string;
  showPreview?: boolean;
  showLabels?: boolean;
}

export const ThumbnailSelector: React.FC<ThumbnailSelectorProps> = ({
  videoUrl,
  videoDuration,
  thumbnailTimestamp,
  onThumbnailTimestampChange,
  className,
  showPreview = true,
  showLabels = true,
}) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const offscreenCanvasRef = useRef<OffscreenCanvas | null>(null);
  const [isGeneratingThumbnail, setIsGeneratingThumbnail] = useState(false);
  const [thumbnailPreview, setThumbnailPreview] = useState<string | null>(null);

  // Track created object URLs for cleanup
  const createdUrlsRef = useRef<Set<string>>(new Set());

  // Function to clean up object URLs
  const cleanupUrls = useCallback(() => {
    createdUrlsRef.current.forEach((url) => {
      URL.revokeObjectURL(url);
    });
    createdUrlsRef.current.clear();
  }, []);

  const generateThumbnail = useCallback(async () => {
    if (!videoRef.current || !videoUrl) return;

    // Clean up previous URLs before generating new ones
    cleanupUrls();

    // Initialize OffscreenCanvas if not already done
    if (!offscreenCanvasRef.current) {
      offscreenCanvasRef.current = new OffscreenCanvas(128, 128);
    }

    setIsGeneratingThumbnail(true);

    try {
      const video = videoRef.current;
      const canvas = offscreenCanvasRef.current;
      const ctx = canvas.getContext('2d');

      if (!ctx) return;

      video.currentTime = thumbnailTimestamp / 1000;

      await new Promise<void>((resolve) => {
        const onSeeked = () => {
          video.removeEventListener('seeked', onSeeked);
          resolve();
        };
        video.addEventListener('seeked', onSeeked);
      });

      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      const blob = await canvas.convertToBlob({
        type: 'image/jpeg',
        quality: 0.8,
      });
      const dataUrl = URL.createObjectURL(blob);
      // Track object URL for cleanup
      createdUrlsRef.current.add(dataUrl);
      setThumbnailPreview(dataUrl);
    } catch (error) {
    } finally {
      setIsGeneratingThumbnail(false);
    }
  }, [thumbnailTimestamp, videoUrl, cleanupUrls]);

  useEffect(() => {
    if (videoUrl && videoDuration > 0) {
      generateThumbnail();
    }
  }, [generateThumbnail, videoUrl, videoDuration]);

  // Cleanup URLs when video URL changes
  useEffect(() => {
    cleanupUrls();
  }, [videoUrl, cleanupUrls]);

  // Cleanup URLs on unmount
  useEffect(() => {
    return () => {
      cleanupUrls();
    };
  }, [cleanupUrls]);

  const handleCurrentTimeSet = useCallback(
    (currentTime: number) => {
      onThumbnailTimestampChange(currentTime);
    },
    [onThumbnailTimestampChange]
  );

  return (
    <div className={clsx('flex flex-col gap-4', className)}>
      <video
        ref={videoRef}
        src={videoUrl}
        style={{ display: 'none' }}
        crossOrigin='anonymous'
      />

      {showPreview && thumbnailPreview && (
        <div className='flex flex-col items-center gap-2'>
          <h3 className='text-sm font-medium text-foreground-primary'>
            Thumbnail Preview
          </h3>
          <div className='relative'>
            <img
              src={thumbnailPreview}
              alt='Thumbnail preview'
              className='h-32 w-32 rounded-lg border border-border-secondary object-cover'
            />
            {isGeneratingThumbnail && (
              <div className='bg-opacity-50 absolute inset-0 flex items-center justify-center rounded-lg bg-black'>
                <div className='h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent' />
              </div>
            )}
          </div>
        </div>
      )}

      <div className='flex flex-col gap-2'>
        {showLabels && (
          <div className='flex items-center justify-between'>
            <span className='text-sm text-foreground-secondary'>
              Select thumbnail frame
            </span>
            <span className='text-sm font-medium text-foreground-primary'>
              {formatTime(thumbnailTimestamp)}
            </span>
          </div>
        )}

        <Trimmer
          start={0}
          end={videoDuration}
          duration={videoDuration}
          current={thumbnailTimestamp}
          onCurrentTimeSet={handleCurrentTimeSet}
          onRangeSet={() => {}} // Not used for thumbnail selection
          className='h-8'
        />

        {showLabels && (
          <div className='flex justify-between text-xs text-foreground-tertiary'>
            <span>0:00</span>
            <span>{formatTime(videoDuration)}</span>
          </div>
        )}
      </div>
    </div>
  );
};
