'use client';

import { useState, useCallback, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { cn } from '@/lib/utils';
import { useUploadFile, useUploadMultipleFiles } from '@/hooks/use-files';
import type { FileUploadOptions } from '@fischerx/types';

interface FileUploaderProps {
  onUploadSuccess?: (files: any[]) => void;
  accept?: string;
  maxSize?: number;
  multiple?: boolean;
  category?: string;
  className?: string;
}

export function FileUploader({
  onUploadSuccess,
  accept,
  maxSize = 10 * 1024 * 1024,
  multiple = false,
  category,
  className,
}: FileUploaderProps) {
  const [isDragging, setIsDragging] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const uploadFile = useUploadFile();
  const uploadMultipleFiles = useUploadMultipleFiles();

  const validateFile = (file: File): string | null => {
    if (maxSize && file.size > maxSize) {
      return `File size must be less than ${(maxSize / 1024 / 1024).toFixed(0)}MB`;
    }
    if (accept) {
      const acceptedTypes = accept.split(',');
      const fileType = file.type;
      const fileName = file.name;
      const isAccepted = acceptedTypes.some(type => {
        if (type.startsWith('.')) {
          return fileName.toLowerCase().endsWith(type.toLowerCase());
        }
        if (type.endsWith('/*')) {
          return fileType.startsWith(type.replace('/*', '/'));
        }
        return fileType === type;
      });
      if (!isAccepted) {
        return 'File type not accepted';
      }
    }
    return null;
  };

  const handleFiles = useCallback(
    async (selectedFiles: FileList | File[]) => {
      const files = Array.from(selectedFiles);
      const errors: string[] = [];

      files.forEach((file) => {
        const error = validateFile(file);
        if (error) {
          errors.push(`${file.name}: ${error}`);
        }
      });

      if (errors.length > 0) {
        alert(errors.join('\n'));
        return;
      }

      const options: FileUploadOptions = category ? { category } : {};

      try {
        setUploadProgress(0);
        let result;
        
        if (multiple && files.length > 1) {
          result = await uploadMultipleFiles.mutateAsync({ files, options });
          if (result.success && onUploadSuccess) {
            onUploadSuccess(result.data);
          }
        } else if (files.length === 1) {
          result = await uploadFile.mutateAsync({ file: files[0], options });
          if (result.success && onUploadSuccess) {
            onUploadSuccess([result.data]);
          }
        }
        
        setUploadProgress(100);
        setTimeout(() => setUploadProgress(0), 1000);
      } catch (error) {
        console.error('Upload failed:', error);
        alert('Upload failed. Please try again.');
      }
    },
    [uploadFile, uploadMultipleFiles, category, multiple, onUploadSuccess, maxSize, accept]
  );

  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(true);
  }, []);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
  }, []);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      setIsDragging(false);
      if (e.dataTransfer.files.length > 0) {
        handleFiles(e.dataTransfer.files);
      }
    },
    [handleFiles]
  );

  const handleFileSelect = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      if (e.target.files && e.target.files.length > 0) {
        handleFiles(e.target.files);
      }
      e.target.value = '';
    },
    [handleFiles]
  );

  const isUploading = uploadFile.isPending || uploadMultipleFiles.isPending;

  return (
    <Card className={className}>
      <CardHeader>
        <CardTitle>Upload Files</CardTitle>
      </CardHeader>
      <CardContent>
        <div
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
          onClick={() => fileInputRef.current?.click()}
          className={cn(
            'flex flex-col items-center justify-center p-8 border-2 border-dashed rounded-lg cursor-pointer transition-colors',
            isDragging
              ? 'border-primary bg-primary/10'
              : 'border-gray-300 hover:border-primary hover:bg-gray-50'
          )}
        >
          <input
            ref={fileInputRef}
            type="file"
            multiple={multiple}
            accept={accept}
            onChange={handleFileSelect}
            className="hidden"
            disabled={isUploading}
          />

          {isUploading ? (
            <div className="text-center">
              <div className="text-lg font-medium mb-2">Uploading...</div>
              <div className="w-48 h-2 bg-gray-200 rounded-full overflow-hidden">
                <div
                  className="h-full bg-primary transition-all duration-300"
                  style={{ width: `${uploadProgress}%` }}
                />
              </div>
            </div>
          ) : (
            <>
              <div className="text-4xl mb-4">📁</div>
              <div className="text-center">
                <p className="text-lg font-medium mb-1">
                  {isDragging ? 'Drop files here' : 'Drag and drop files here'}
                </p>
                <p className="text-sm text-muted-foreground mb-4">or click to browse</p>
                <Button variant="default" disabled={isUploading}>
                  Select Files
                </Button>
              </div>
            </>
          )}
        </div>

        {uploadFile.error && (
          <div className="mt-4 p-3 bg-destructive/10 text-destructive rounded-md">
            Error uploading file: {uploadFile.error.message}
          </div>
        )}
        {uploadMultipleFiles.error && (
          <div className="mt-4 p-3 bg-destructive/10 text-destructive rounded-md">
            Error uploading files: {uploadMultipleFiles.error.message}
          </div>
        )}
      </CardContent>
    </Card>
  );
}
