/**
 * Upload dropzone for DMS file browser.
 * Supports drag-and-drop and click-to-select file uploads with progress.
 */

import React, { useCallback, useRef, useState } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { uploadFile } from '@/api/dms';
import { useToast } from '@/components/ui/Toast';

export interface UploadDropzoneProps {
  folderId: string | null;
  onUploaded: () => void;
}

interface UploadProgress {
  fileName: string;
  progress: number;
  error: string | null;
}

export function UploadDropzone({ folderId, onUploaded }: UploadDropzoneProps) {
  const { t } = useTranslation();
  const toast = useToast();
  const inputRef = useRef<HTMLInputElement>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [uploads, setUploads] = useState<UploadProgress[]>([]);
  const [isUploading, setIsUploading] = useState(false);

  const handleFiles = useCallback(async (fileList: FileList) => {
    const files = Array.from(fileList);
    if (files.length === 0) return;

    setIsUploading(true);
    const progressEntries = files.map((f) => ({ fileName: f.name, progress: 0, error: null as string | null }));
    setUploads(progressEntries);

    let allSuccess = true;
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      try {
        setUploads((prev) => prev.map((u, idx) => idx === i ? { ...u, progress: 50 } : u));
        await uploadFile(file, folderId);
        setUploads((prev) => prev.map((u, idx) => idx === i ? { ...u, progress: 100 } : u));
      } catch (err) {
 allSuccess = false;
        const errorMsg = err instanceof Error ? err.message : String(err);
        setUploads((prev) => prev.map((u, idx) => idx === i ? { ...u, error: errorMsg } : u));
      }
    }

    setIsUploading(false);
    if (allSuccess) {
      toast.success(t('dms.uploadSuccess'));
    } else {
      toast.error(t('dms.uploadError'));
    }
    onUploaded();
    setTimeout(() => setUploads([]), 3000);
  }, [folderId, onUploaded, toast, t]);

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

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

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

  const handleClick = useCallback(() => {
    inputRef.current?.click();
  }, []);

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

  return (
    <div data-testid="upload-dropzone">
      <div
        className={clsx(
          'border-2 border-dashed rounded-lg p-8 text-center cursor-pointer motion-safe:transition-all',
          'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
          isDragging
            ? 'border-primary-500 bg-primary-50'
            : 'border-secondary-300 hover:border-secondary-400 bg-secondary-50'
        )}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
        onClick={handleClick}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            handleClick();
          }
        }}
        tabIndex={0}
        role="button"
        aria-label={t('dms.uploadDropHere')}
      >
        <input
          ref={inputRef}
          type="file"
          multiple
          onChange={handleInputChange}
          className="hidden"
          aria-hidden="true"
        />
        <svg className="mx-auto h-10 w-10 text-secondary-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} 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="mt-2 text-sm text-secondary-600">{t('dms.uploadDropHere')}</p>
      </div>
      {uploads.length > 0 && (
        <div className="mt-4 space-y-2" data-testid="upload-progress-list">
          {uploads.map((u, i) => (
            <div key={i} className="bg-white rounded-md border border-secondary-200 p-3">
              <div className="flex items-center justify-between mb-1">
                <span className="text-sm text-secondary-700 truncate">{u.fileName}</span>
                {u.error ? (
                  <span className="text-xs text-danger-600">{u.error}</span>
                ) : (
                  <span className="text-xs text-secondary-500">{u.progress}%</span>
                )}
              </div>
              <div className="h-2 bg-secondary-100 rounded-full overflow-hidden">
                <div
                  className={clsx('h-full rounded-full transition-all', u.error ? 'bg-danger-500' : 'bg-primary-500')}
                  style={{ width: `${u.error ? 100 : u.progress}%` }}
                  role="progressbar"
                  aria-valuenow={u.error ? 100 : u.progress}
                  aria-valuemin={0}
                  aria-valuemax={100}
                />
              </div>
            </div>
          ))}
        </div>
      )}
      {isUploading && (
        <div className="mt-2 text-sm text-secondary-500" data-testid="upload-indicator">
          {t('dms.uploading')}...
        </div>
      )}
    </div>
  );
}
