'use client';

import { useState, useCallback, useRef, type DragEvent } from 'react';
import { Button } from '@/components/ui/Button';
import {
  uploadFile,
  ALLOWED_MIME_TYPES,
  MAX_FILE_SIZE_MB,
  MAX_FILE_SIZE_BYTES,
  type FileResponse,
} from '@/lib/files';

interface FileUploadProps {
  vehicleId: string;
  onUploadComplete?: (file: FileResponse) => void;
  onUploadError?: (error: string) => void;
}

interface UploadStatus {
  filename: string;
  status: 'pending' | 'uploading' | 'success' | 'error';
  error?: string;
}

export function FileUpload({ vehicleId, onUploadComplete, onUploadError }: FileUploadProps) {
  const [isDragging, setIsDragging] = useState(false);
  const [uploadStatuses, setUploadStatuses] = useState<UploadStatus[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const validateFile = (file: File): string | null => {
    if (!ALLOWED_MIME_TYPES.includes(file.type)) {
      return `Unsupported file type: ${file.type || 'unknown'}`;
    }
    if (file.size > MAX_FILE_SIZE_BYTES) {
      return `File size exceeds ${MAX_FILE_SIZE_MB}MB limit`;
    }
    return null;
  };

  const handleFiles = useCallback(async (files: FileList) => {
    setIsUploading(true);
    const fileArray = Array.from(files);
    const statuses: UploadStatus[] = fileArray.map((f) => ({
      filename: f.name,
      status: 'pending' as const,
    }));
    setUploadStatuses(statuses);

    for (let i = 0; i < fileArray.length; i++) {
      const file = fileArray[i];
      const validationError = validateFile(file);

      if (validationError) {
        setUploadStatuses((prev) =>
          prev.map((s, idx) =>
            idx === i ? { ...s, status: 'error', error: validationError } : s
          )
        );
        onUploadError?.(validationError);
        continue;
      }

      setUploadStatuses((prev) =>
        prev.map((s, idx) =>
          idx === i ? { ...s, status: 'uploading' } : s
        )
      );

      try {
        const result = await uploadFile(vehicleId, file);
        setUploadStatuses((prev) =>
          prev.map((s, idx) =>
            idx === i ? { ...s, status: 'success' } : s
          )
        );
        onUploadComplete?.(result);
      } catch (err: unknown) {
        const apiErr = err as { error?: { message?: string } };
        const errorMsg = apiErr?.error?.message || 'Upload failed';
        setUploadStatuses((prev) =>
          prev.map((s, idx) =>
            idx === i ? { ...s, status: 'error', error: errorMsg } : s
          )
        );
        onUploadError?.(errorMsg);
      }
    }

    setIsUploading(false);
    // Clear statuses after 3 seconds
    setTimeout(() => setUploadStatuses([]), 3000);
  }, [vehicleId, onUploadComplete, onUploadError]);

  const handleDragEnter = useCallback((e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(true);
  }, []);

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

  const handleDragOver = useCallback((e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
  }, []);

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

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      handleFiles(e.target.files);
      // Reset input so same file can be selected again
      e.target.value = '';
    }
  };

  return (
    <div className="w-full" data-testid="file-upload">
      <div
        onDragEnter={handleDragEnter}
        onDragLeave={handleDragLeave}
        onDragOver={handleDragOver}
        onDrop={handleDrop}
        onClick={() => inputRef.current?.click()}
        className={`
          border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors
          ${isDragging
            ? 'border-primary bg-primary/5'
            : 'border-border hover:border-primary/50'
          }
        `}
        data-testid="dropzone"
      >
        <input
          ref={inputRef}
          type="file"
          multiple
          accept=".jpg,.jpeg,.png,.webp,.pdf,.doc,.docx"
          onChange={handleInputChange}
          className="hidden"
          data-testid="file-input"
        />
        <div className="flex flex-col items-center gap-2">
          <svg
            className="h-12 w-12 text-text-muted"
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
            />
          </svg>
          <p className="text-text font-medium">
            {isDragging ? 'Drop files here' : 'Drag & drop files or click to browse'}
          </p>
          <p className="text-text-muted text-sm">
            Supports: JPG, PNG, WebP, PDF, DOC, DOCX (max {MAX_FILE_SIZE_MB}MB)
          </p>
        </div>
      </div>

      {uploadStatuses.length > 0 && (
        <div className="mt-4 space-y-2" data-testid="upload-statuses">
          {uploadStatuses.map((status, idx) => (
            <div
              key={idx}
              className={`flex items-center justify-between p-2 rounded ${
                status.status === 'success'
                  ? 'bg-success/10 text-success'
                  : status.status === 'error'
                  ? 'bg-error/10 text-error'
                  : 'bg-surface text-text'
              }`}
              data-testid={`upload-status-${idx}`}
            >
              <span className="text-sm">{status.filename}</span>
              <span className="text-sm font-medium">
                {status.status === 'pending' && 'Pending...'}
                {status.status === 'uploading' && 'Uploading...'}
                {status.status === 'success' && '✓ Uploaded'}
                {status.status === 'error' && `✗ ${status.error}`}
              </span>
            </div>
          ))}
        </div>
      )}

      {isUploading && (
        <div className="mt-2">
          <Button variant="secondary" disabled loading>
            Uploading...
          </Button>
        </div>
      )}
    </div>
  );
}
