'use client';

import * as React from 'react';
import { Upload, X, File, FileVideo, FileAudio, FileImage, Clock, HardDrive, Film } from 'lucide-react';
import { cn } from '@/lib/utils/cn';
import { Button } from '@/components/ui/button';
import type { ConversionFormat } from '@/types/media';

export interface FileUploadProps {
  onFileSelect: (files: File[]) => void;
  onFileRemove: (index: number) => void;
  selectedFiles?: File[];
  accept?: string;
  maxSizeMB?: number;
  disabled?: boolean;
  inputRef?: React.RefObject<HTMLInputElement | null>;
  inputFormat?: ConversionFormat;
}

export function FileUpload({
  onFileSelect,
  onFileRemove,
  selectedFiles = [],
  accept,
  maxSizeMB = 500,
  disabled = false,
  inputRef,
  inputFormat,
}: FileUploadProps) {
  const [isDragging, setIsDragging] = React.useState(false);
  const [fileMetadata, setFileMetadata] = React.useState<Record<number, any>>({});
  const localFileInputRef = React.useRef<HTMLInputElement>(null);
  const fileInputRef = inputRef || localFileInputRef;

  // Extract metadata for files
  React.useEffect(() => {
    const extractMetadata = async () => {
      if (selectedFiles.length === 0 || !inputFormat) {
        setFileMetadata({});
        return;
      }

      const metadata: Record<number, any> = {};

      for (let i = 0; i < selectedFiles.length; i++) {
        const file = selectedFiles[i];
        const baseMetadata = {
          name: file.name,
          size: file.size < 1024 * 1024 ? `${(file.size / 1024).toFixed(2)} KB` : `${(file.size / (1024 * 1024)).toFixed(2)} MB`,
          type: inputFormat.name,
        };

        // Extract media-specific metadata
        if (inputFormat.category === 'video' && file.type.startsWith('video/')) {
          try {
            const video = document.createElement('video');
            video.preload = 'metadata';

            const metadataPromise = new Promise<any>((resolve) => {
              video.onloadedmetadata = () => {
                const duration = video.duration;
                const minutes = Math.floor(duration / 60);
                const seconds = Math.floor(duration % 60);
                resolve({
                  ...baseMetadata,
                  duration: `${minutes}:${seconds.toString().padStart(2, '0')}`,
                  dimensions: `${video.videoWidth} × ${video.videoHeight}`,
                });
                URL.revokeObjectURL(video.src);
              };

              video.onerror = () => {
                resolve(baseMetadata);
                URL.revokeObjectURL(video.src);
              };
            });

            video.src = URL.createObjectURL(file);
            metadata[i] = await metadataPromise;
          } catch (error) {
            metadata[i] = baseMetadata;
          }
        } else if (inputFormat.category === 'audio' && file.type.startsWith('audio/')) {
          try {
            const audio = document.createElement('audio');
            audio.preload = 'metadata';

            const metadataPromise = new Promise<any>((resolve) => {
              audio.onloadedmetadata = () => {
                const duration = audio.duration;
                const minutes = Math.floor(duration / 60);
                const seconds = Math.floor(duration % 60);
                resolve({
                  ...baseMetadata,
                  duration: `${minutes}:${seconds.toString().padStart(2, '0')}`,
                });
                URL.revokeObjectURL(audio.src);
              };

              audio.onerror = () => {
                resolve(baseMetadata);
                URL.revokeObjectURL(audio.src);
              };
            });

            audio.src = URL.createObjectURL(file);
            metadata[i] = await metadataPromise;
          } catch (error) {
            metadata[i] = baseMetadata;
          }
        } else if (inputFormat.category === 'image' && file.type.startsWith('image/')) {
          try {
            const img = new Image();

            const metadataPromise = new Promise<any>((resolve) => {
              img.onload = () => {
                resolve({
                  ...baseMetadata,
                  dimensions: `${img.width} × ${img.height}`,
                });
                URL.revokeObjectURL(img.src);
              };

              img.onerror = () => {
                resolve(baseMetadata);
                URL.revokeObjectURL(img.src);
              };
            });

            img.src = URL.createObjectURL(file);
            metadata[i] = await metadataPromise;
          } catch (error) {
            metadata[i] = baseMetadata;
          }
        } else {
          metadata[i] = baseMetadata;
        }
      }

      setFileMetadata(metadata);
    };

    extractMetadata();
  }, [selectedFiles, inputFormat]);

  const getCategoryIcon = () => {
    if (!inputFormat) return <File className="h-5 w-5 text-primary" />;
    switch (inputFormat.category) {
      case 'video':
        return <FileVideo className="h-5 w-5 text-primary" />;
      case 'audio':
        return <FileAudio className="h-5 w-5 text-primary" />;
      case 'image':
        return <FileImage className="h-5 w-5 text-primary" />;
      default:
        return <File className="h-5 w-5 text-primary" />;
    }
  };

  const handleDragEnter = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    if (!disabled) {
      setIsDragging(true);
    }
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
  };

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);

    if (disabled) return;

    const files = Array.from(e.dataTransfer.files);
    if (files.length > 0) {
      handleFiles(files);
    }
  };

  const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);
    if (files.length > 0) {
      handleFiles(files);
    }
  };

  const handleFiles = (files: File[]) => {
    // Check file sizes
    const maxBytes = maxSizeMB * 1024 * 1024;
    const validFiles = files.filter(file => {
      if (file.size > maxBytes) {
        alert(`${file.name} exceeds ${maxSizeMB}MB limit and will be skipped.`);
        return false;
      }
      return true;
    });

    if (validFiles.length > 0) {
      onFileSelect(validFiles);
    }

    // Reset input
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  const handleClick = () => {
    if (!disabled) {
      fileInputRef.current?.click();
    }
  };

  const handleRemove = (index: number) => (e: React.MouseEvent) => {
    e.stopPropagation();
    onFileRemove(index);
  };

  return (
    <div className="w-full space-y-3">
      <input
        ref={fileInputRef}
        type="file"
        multiple
        className="hidden"
        accept={accept}
        onChange={handleFileInput}
        disabled={disabled}
      />

      {selectedFiles.length > 0 ? (
        <div className="space-y-3">
          {selectedFiles.map((file, index) => {
            const metadata = fileMetadata[index];
            return (
              <div key={`${file.name}-${index}`} className="border border-border rounded-xl p-4 bg-card/50 backdrop-blur-sm">
                <div className="flex items-start gap-3">
                  <div className="p-2 bg-primary/10 rounded-lg shrink-0">
                    {getCategoryIcon()}
                  </div>
                  <div className="flex-1 min-w-0">
                    <div className="flex items-start justify-between gap-2">
                      <p className="text-sm font-medium text-foreground truncate" title={file.name}>
                        {file.name}
                      </p>
                      <Button
                        variant="ghost"
                        size="icon-xs"
                        onClick={handleRemove(index)}
                        disabled={disabled}
                        className="rounded-full hover:bg-destructive/10 hover:text-destructive shrink-0"
                      >
                        <X className="h-3.5 w-3.5" />
                        <span className="sr-only">Remove file</span>
                      </Button>
                    </div>
                    {metadata && (
                      <div className="mt-1.5 flex flex-wrap gap-3 text-[10px] text-muted-foreground">
                        {/* File Size */}
                        <div className="flex items-center gap-1">
                          <HardDrive className="h-3 w-3" />
                          <span>{metadata.size}</span>
                        </div>

                        {/* Type */}
                        <div className="flex items-center gap-1">
                          <File className="h-3 w-3" />
                          <span>{metadata.type}</span>
                        </div>

                        {/* Duration (for video/audio) */}
                        {metadata.duration && (
                          <div className="flex items-center gap-1">
                            <Clock className="h-3 w-3" />
                            <span>{metadata.duration}</span>
                          </div>
                        )}

                        {/* Dimensions */}
                        {metadata.dimensions && (
                          <div className="flex items-center gap-1">
                            {inputFormat?.category === 'video' ? (
                              <Film className="h-3 w-3" />
                            ) : (
                              <FileImage className="h-3 w-3" />
                            )}
                            <span>{metadata.dimensions}</span>
                          </div>
                        )}
                      </div>
                    )}
                  </div>
                </div>
              </div>
            );
          })}

          {/* Add more files button */}
          <Button
            variant="outline"
            onClick={handleClick}
            disabled={disabled}
            className="w-full"
          >
            <Upload className="h-3.5 w-3.5 mr-1.5" />
            Add More Files
          </Button>
        </div>
      ) : (
        <div
          onClick={handleClick}
          onDragEnter={handleDragEnter}
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
          className={cn(
            'border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all duration-200',
            'hover:border-primary/40 hover:bg-primary/5',
            {
              'border-primary bg-primary/10 scale-[0.98]': isDragging,
              'border-border/50': !isDragging,
              'opacity-50 cursor-not-allowed': disabled,
            }
          )}
        >
          <div className="bg-primary/10 w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-3">
            <Upload className="h-6 w-6 text-primary" />
          </div>
          <p className="text-sm font-medium text-foreground mb-0.5">
            Drop files here or click to browse
          </p>
          <p className="text-[10px] text-muted-foreground">
            Max {maxSizeMB}MB per file
          </p>
        </div>
      )}
    </div>
  );
}
