'use client';

import React from 'react';
import { useDropzone } from 'react-dropzone';
import { toast } from 'sonner';
import { Loader2, ImageUp, X, Image as ImageIcon } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { cn } from '@/lib/utils/cn';

interface UploadedFile {
  id: string;
  url: string;
  name: string;
  size: number;
  type: string;
}

interface FileUploadProps {
  onUploadComplete?: (files: UploadedFile[]) => void;
  onUploadError?: (error: string) => void;
  maxFiles?: number;
  maxFileSize?: number;
  acceptedFileTypes?: string[];
  disabled?: boolean;
  className?: string;
  showPreview?: boolean;
  metadata?: Record<string, any>;
  existingFiles?: UploadedFile[]; // For displaying existing files
}

export function FileUpload({
  onUploadComplete,
  onUploadError,
  maxFiles = 5,
  maxFileSize = 10 * 1024 * 1024, // 10MB
  acceptedFileTypes = ['image/*'],
  disabled = false,
  className,
  showPreview = true,
  metadata = {},
  existingFiles = []
}: FileUploadProps) {
  const [uploading, setUploading] = React.useState(false);
  const [uploadedFiles, setUploadedFiles] = React.useState<UploadedFile[]>(existingFiles);

  // Update uploadedFiles when existingFiles changes
  React.useEffect(() => {
    setUploadedFiles(existingFiles);
  }, [existingFiles]);

  // Convert acceptedFileTypes array to object format for react-dropzone
  const acceptObject = React.useMemo(() => {
    const obj: Record<string, string[]> = {};
    acceptedFileTypes.forEach((type) => {
      obj[type] = [];
    });
    return obj;
  }, [acceptedFileTypes]);

  const onDrop = React.useCallback(
    async (acceptedFiles: File[]) => {
      if (disabled || uploading) return;

      // Check file count limit
      if (uploadedFiles.length + acceptedFiles.length > maxFiles) {
        const error = `Cannot upload more than ${maxFiles} file${maxFiles === 1 ? '' : 's'}`;
        toast.error(error);
        onUploadError?.(error);
        return;
      }

      setUploading(true);

      console.log('[FileUpload] Starting upload process', {
        filesCount: acceptedFiles.length,
        fileNames: acceptedFiles.map(f => f.name),
        metadata
      });

      try {
        const formData = new FormData();

        acceptedFiles.forEach((file) => {
          formData.append('files', file);
        });

        const payloadMetadata = {
          ...metadata
        };

        formData.append('metadata', JSON.stringify(payloadMetadata));

        console.log('[FileUpload] Uploading via API route', {
          files: acceptedFiles.map((file) => ({
            name: file.name,
            size: file.size,
            type: file.type
          })),
          metadata: payloadMetadata
        });

        const response = await fetch('/api/upload', {
          method: 'POST',
          body: formData
        });

        if (!response.ok) {
          const errorResponse = await response.json().catch(() => null);
          const message =
            errorResponse?.error ||
            `Upload failed with status ${response.status}`;
          throw new Error(message);
        }

        const uploadResults = await response.json();
        const resultsArray = Array.isArray(uploadResults)
          ? uploadResults
          : [uploadResults];

        const newFiles: UploadedFile[] = resultsArray.map((result) => {
          const fileUrl = result.publicUrl || result.url;
          return {
            id: result.id,
            url: fileUrl,
            name:
              result.name ||
              result.path?.split('/').pop() ||
              acceptedFiles.find((file) => file.name === result.name)?.name ||
              'unknown',
            size:
              result.size ??
              acceptedFiles.find((file) => file.name === result.name)?.size ??
              0,
            type:
              result.type ??
              acceptedFiles.find((file) => file.name === result.name)?.type ??
              'unknown'
          };
        });

        console.log('[FileUpload] Upload results received', newFiles);

        setUploadedFiles((prev) => [...prev, ...newFiles]);
        onUploadComplete?.(newFiles);

        toast.success(
          `Successfully uploaded ${newFiles.length} file${newFiles.length === 1 ? '' : 's'}`
        );
      } catch (error) {
        console.error('[FileUpload] Upload error', error);
        const errorMessage =
          error instanceof Error ? error.message : 'Upload failed';
        toast.error(errorMessage);
        onUploadError?.(errorMessage);
      } finally {
        setUploading(false);
      }
    },
    [
      disabled,
      uploading,
      uploadedFiles.length,
      maxFiles,
      metadata,
      onUploadComplete,
      onUploadError
    ]
  );

  const removeFile = React.useCallback((fileId: string) => {
    setUploadedFiles((prev) => prev.filter((file) => file.id !== fileId));
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: acceptObject,
    maxSize: maxFileSize,
    disabled: disabled || uploading,
    multiple: maxFiles > 1
  });

  return (
    <div className={cn('space-y-4', className)}>
      {/* Upload Area */}
      <Card>
        <CardContent className='p-6'>
          <div
            {...getRootProps()}
            className={cn(
              'border-muted-foreground/25 cursor-pointer rounded-lg border-2 border-dashed p-8 text-center transition-colors',
              isDragActive && 'border-primary bg-primary/10',
              (disabled || uploading) && 'cursor-not-allowed opacity-50',
              'hover:border-primary hover:bg-primary/5'
            )}
          >
            <input {...getInputProps()} />

            {uploading ? (
              <div className='flex flex-col items-center space-y-2'>
                <Loader2 className='text-primary h-8 w-8 animate-spin' />
                <p className='text-muted-foreground text-sm'>Uploading...</p>
              </div>
            ) : (
              <div className='flex flex-col items-center space-y-2'>
                <ImageUp className='text-muted-foreground h-6 w-6' />
              </div>
            )}
          </div>
        </CardContent>
      </Card>

      {/* File Preview */}
      {showPreview && uploadedFiles.length > 0 && (
        <Card>
          <CardContent className='p-6'>
            <h4 className='mb-3 font-medium'>Uploaded Files</h4>
            <div className='space-y-2'>
              {uploadedFiles.map((file) => (
                <div
                  key={file.id}
                  className='bg-muted/50 flex items-center justify-between rounded-lg p-3'
                >
                  <div className='flex items-center space-x-3'>
                    <ImageIcon className='text-muted-foreground h-5 w-5' />
                    <div>
                      <p className='max-w-48 truncate text-sm font-medium'>
                        {file.name}
                      </p>
                      <p className='text-muted-foreground text-xs'>
                        {(file.size / 1024 / 1024).toFixed(2)} MB
                      </p>
                    </div>
                  </div>
                  <Button
                    variant='ghost'
                    size='sm'
                    onClick={() => removeFile(file.id)}
                    className='h-8 w-8 p-0'
                  >
                    <X className='h-4 w-4' />
                  </Button>
                </div>
              ))}
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}
