'use client';

import { useCallback, useState } from 'react';
import { useDropzone } from 'react-dropzone';
import { Upload, X, FileImage, FileVideo, FileAudio, File as FileIcon } from 'lucide-react';
import { clsx } from 'clsx';

interface FileUploadProps {
  onUpload?: (file: File) => void;
  onUploadMultiple?: (files: File[]) => void;
  accept?: Record<string, string[]>;
  maxSize?: number;
  label?: string;
  currentFile?: File | null;
  onClear?: () => void;
  multiple?: boolean;
}

const fileIcons: Record<string, any> = {
  image: FileImage,
  video: FileVideo,
  audio: FileAudio,
};

export default function FileUpload({
  onUpload,
  onUploadMultiple,
  accept,
  maxSize = 100 * 1024 * 1024, // 100MB default
  label = 'Upload a file',
  currentFile,
  onClear,
  multiple = false,
}: FileUploadProps) {
  const [error, setError] = useState<string | null>(null);

  const onDrop = useCallback(
    (acceptedFiles: File[], rejectedFiles: any[]) => {
      setError(null);

      if (rejectedFiles.length > 0) {
        const rejection = rejectedFiles[0];
        if (rejection.errors[0]?.code === 'file-too-large') {
          setError(`File too large. Max size is ${Math.round(maxSize / 1024 / 1024)}MB`);
        } else if (rejection.errors[0]?.code === 'file-invalid-type') {
          setError('Invalid file type');
        } else {
          setError('File rejected');
        }
        return;
      }

      if (acceptedFiles.length > 0) {
        if (onUploadMultiple) {
          onUploadMultiple(acceptedFiles);
        } else if (onUpload) {
          onUpload(acceptedFiles[0]);
        }
      }
    },
    [onUpload, onUploadMultiple, maxSize]
  );

  // Helper to validate mime type against accept prop
  const checkType = (file: File) => {
    if (!accept) return true;
    const fileType = file.type;
    const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;

    // Iterate over accept keys (image/*, etc)
    for (const [mime, exts] of Object.entries(accept)) {
      if (mime === '*/*') return true;
      // Check wildcard
      if (mime.endsWith('/*')) {
        const baseMime = mime.split('/')[0];
        if (fileType.startsWith(baseMime + '/')) return true;
      }
      // Check exact mime
      if (fileType === mime) return true;
      // Check extensions
      if (exts && exts.some(ext => ext.toLowerCase() === fileExt)) return true;
    }
    return false;
  };

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept,
    maxSize,
    multiple: multiple || !!onUploadMultiple,
  });

  const getFileIcon = (file: File) => {
    const type = file.type.split('/')[0];
    const Icon = fileIcons[type] || FileIcon;
    return <Icon className="w-8 h-8 text-forge-yellow" />;
  };

  const formatFileSize = (bytes: number) => {
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
  };

  if (currentFile) {
    return (
      <div className="bg-forge-dark rounded-xl p-4 border border-gray-700">
        <div className="flex items-center gap-4">
          {getFileIcon(currentFile)}
          <div className="flex-1 min-w-0">
            <p className="text-white font-medium truncate">{currentFile.name}</p>
            <p className="text-sm text-gray-500">{formatFileSize(currentFile.size)}</p>
          </div>
          {onClear && (
            <button
              onClick={onClear}
              className="p-2 text-gray-400 hover:text-red-400 transition-colors"
            >
              <X className="w-5 h-5" />
            </button>
          )}
        </div>
      </div>
    );
  }

  return (
    <div
      onDragOver={(e) => {
        // Needed to allow dropping non-files (like our JSON asset)
        if (e.dataTransfer.types.includes('application/json')) {
          e.preventDefault();
          e.dataTransfer.dropEffect = 'copy';
        }
      }}
      onDrop={async (e) => {
        // Check if we dropped our custom asset
        const jsonData = e.dataTransfer.getData('application/json');
        if (jsonData) {
          try {
            const data = JSON.parse(jsonData);
            if (data.type === 'forge-asset' && data.url) {
              e.preventDefault();
              e.stopPropagation();

              const res = await fetch(data.url);
              const blob = await res.blob();
              const file = new File([blob], data.filename, { type: blob.type });

              // Validate type
              if (!checkType(file)) {
                setError('Invalid file type for this tool');
                return;
              }

              if (onUploadMultiple) {
                onUploadMultiple([file]);
              } else if (onUpload) {
                onUpload(file);
              }
            }
          } catch (err) {
            // Not our JSON, ignore
          }
        }
      }}
    >
      <div
        {...getRootProps()}
        data-file-drop-zone="true"
        className={clsx(
          'upload-zone',
          isDragActive && 'active'
        )}
      >
        <input {...getInputProps()} />
        <Upload className="w-12 h-12 text-gray-500 mx-auto mb-4" />
        <p className="text-white font-medium mb-2">{label}</p>
        <p className="text-gray-500 text-sm">
          Drag and drop or <span className="text-forge-yellow">browse</span>
        </p>
        {accept && (
          <p className="text-gray-600 text-xs mt-2">
            Accepted: {Object.keys(accept).join(', ')}
          </p>
        )}
      </div>
      {error && (
        <p className="mt-2 text-sm text-red-400">{error}</p>
      )}
    </div>
  );
}
