import { useState, useRef, useCallback } from 'react';
import { Button } from './button';
import { cn } from '@/lib/utils';
import { Upload, X, User, Loader2 } from 'lucide-react';
import { useToast } from '@/hooks/useToast';
import { logger } from '@/utils/logger';
import { parseApiError } from '@/utils/apiErrorHandler';

/**
 * FE-COMP-009: Avatar upload component with drag-and-drop and preview
 */

/**
 * AvatarUploadProps - Propriétés du composant AvatarUpload
 *
 * @interface AvatarUploadProps
 */
export interface AvatarUploadProps {
  /**
   * ID de l'utilisateur pour lequel uploader l'avatar
   */
  userId: string | number;

  /**
   * URL de l'avatar actuel (pour affichage)
   */
  currentAvatarUrl?: string | null;

  /**
   * Fonction appelée après un upload réussi
   *
   * @param {string} avatarUrl - URL du nouvel avatar
   */
  onAvatarUpdated?: (avatarUrl: string) => void;

  /**
   * Fonction appelée après une suppression réussie
   */
  onAvatarDeleted?: () => void;

  /**
   * Taille de l'avatar
   *
   * - `sm`: 20x20 (80px)
   * - `md`: 32x32 (128px)
   * - `lg`: 40x40 (160px) - par défaut
   * - `xl`: 48x48 (192px)
   *
   * @default 'lg'
   */
  size?: 'sm' | 'md' | 'lg' | 'xl';

  /**
   * Classes CSS personnalisées
   */
  className?: string;

  /**
   * Si `true`, désactive le composant
   *
   * @default false
   */
  disabled?: boolean;

  /**
   * Taille maximale du fichier en bytes
   *
   * @default 5242880 (5MB)
   */
  maxSize?: number;

  /**
   * Types de fichiers acceptés (attribut accept)
   *
   * @default 'image/*'
   */
  accept?: string;
}

/**
 * AvatarUpload - Composant d'upload d'avatar avec drag-and-drop et preview
 *
 * Composant pour uploader et gérer les avatars utilisateur avec :
 * - Drag and drop
 * - Preview avant upload
 * - Validation de taille et type
 * - Suppression d'avatar
 * - États de chargement
 *
 * FE-COMP-009: Avatar upload component with drag-and-drop and preview
 *
 * @example
 * ```tsx
 * // Upload d'avatar simple
 * <AvatarUpload
 *   userId={user.id}
 *   currentAvatarUrl={user.avatar}
 *   onAvatarUpdated={(url) => updateUserAvatar(url)}
 * />
 * ```
 *
 * @example
 * ```tsx
 * // Avec taille personnalisée et validation
 * <AvatarUpload
 *   userId={user.id}
 *   size="xl"
 *   maxSize={10 * 1024 * 1024} // 10MB
 *   accept="image/jpeg,image/png"
 *   onAvatarUpdated={handleUpdate}
 *   onAvatarDeleted={handleDelete}
 * />
 * ```
 *
 * @component
 * @param {AvatarUploadProps} props - Propriétés du composant
 * @returns {JSX.Element} Zone d'upload avec preview et contrôles
 */

const sizeClasses = {
  sm: 'w-20 h-20',
  md: 'w-32 h-32',
  lg: 'w-40 h-40',
  xl: 'w-48 h-48',
};

const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB default

/**
 * Avatar upload component with drag-and-drop, preview, and validation
 */
export function AvatarUpload({
  userId,
  currentAvatarUrl,
  onAvatarUpdated,
  onAvatarDeleted,
  size = 'lg',
  className,
  disabled = false,
  maxSize = MAX_FILE_SIZE,
  accept = 'image/*',
}: AvatarUploadProps) {
  const [dragActive, setDragActive] = useState(false);
  const [preview, setPreview] = useState<string | null>(
    currentAvatarUrl || null,
  );
  const [isUploading, setIsUploading] = useState(false);
  const [isDeleting, setIsDeleting] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const { success: showSuccess, error: showError } = useToast();

  // Dynamically import usersApi to avoid circular dependencies
  const uploadAvatar = useCallback(
    async (file: File) => {
      const { usersApi } = await import('@/services/api/users');
      return usersApi.uploadAvatar(String(userId), file);
    },
    [userId],
  );

  const deleteAvatar = useCallback(async () => {
    const { usersApi } = await import('@/services/api/users');
    return usersApi.deleteAvatar(String(userId));
  }, [userId]);

  const validateFile = useCallback(
    (file: File): string | null => {
      // Validate file type
      if (!file.type.startsWith('image/')) {
        return 'Le fichier doit être une image';
      }

      // Validate file size
      if (file.size > maxSize) {
        const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(1);
        return `Le fichier est trop volumineux (max ${maxSizeMB}MB)`;
      }

      return null;
    },
    [maxSize],
  );

  const createPreview = useCallback((file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e) => resolve(e.target?.result as string);
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  }, []);

  const handleFileSelect = useCallback(
    async (file: File) => {
      const error = validateFile(file);
      if (error) {
        showError(`Erreur de validation: ${error}`);
        return;
      }

      // Create preview
      try {
        const previewUrl = await createPreview(file);
        setPreview(previewUrl);
      } catch (err: unknown) {
        const apiError = parseApiError(err);
        logger.error('Error creating preview', {
          error: apiError.message,
          stack: err instanceof Error ? err.stack : undefined,
        });
      }

      // Upload file
      setIsUploading(true);
      try {
        const response = await uploadAvatar(file);
        setPreview(response.avatar_url);
        onAvatarUpdated?.(response.avatar_url);
        showSuccess('Votre avatar a été mis à jour avec succès.');
        onAvatarUpdated?.(response.avatar_url);
        showSuccess('Votre avatar a été mis à jour avec succès.');
      } catch (error: unknown) {
        const apiError = parseApiError(error);
        logger.error('Error uploading avatar', {
          error: apiError.message,
          stack: error instanceof Error ? error.stack : undefined,
          userId: String(userId),
        });
        showError(apiError.message);
        // Revert preview to original
        setPreview(currentAvatarUrl || null);
      } finally {
        setIsUploading(false);
        if (fileInputRef.current) {
          fileInputRef.current.value = '';
        }
      }
    },
    [
      validateFile,
      createPreview,
      uploadAvatar,
      onAvatarUpdated,
      showSuccess,
      showError,
      currentAvatarUrl,
    ],
  );

  const handleDrag = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === 'dragenter' || e.type === 'dragover') {
      setDragActive(true);
    } else if (e.type === 'dragleave') {
      setDragActive(false);
    }
  }, []);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      e.stopPropagation();
      setDragActive(false);

      if (disabled || isUploading) return;

      if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
        const file = e.dataTransfer.files[0];
        handleFileSelect(file);
      }
    },
    [disabled, isUploading, handleFileSelect],
  );

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

  const handleClick = useCallback(() => {
    if (!disabled && !isUploading && fileInputRef.current) {
      fileInputRef.current.click();
    }
  }, [disabled, isUploading]);

  const handleDelete = useCallback(async () => {
    if (!currentAvatarUrl || isDeleting) return;

    setIsDeleting(true);
    try {
      await deleteAvatar();
      setPreview(null);
      onAvatarDeleted?.();
      showSuccess('Votre avatar a été supprimé avec succès.');
      onAvatarDeleted?.();
      showSuccess('Votre avatar a été supprimé avec succès.');
    } catch (error: unknown) {
      const apiError = parseApiError(error);
      logger.error('Error deleting avatar', {
        error: apiError.message,
        stack: error instanceof Error ? error.stack : undefined,
        userId: String(userId),
      });
      showError(apiError.message);
    } finally {
      setIsDeleting(false);
    }
  }, [
    currentAvatarUrl,
    isDeleting,
    deleteAvatar,
    onAvatarDeleted,
    showSuccess,
    showError,
  ]);

  const sizeClass = sizeClasses[size];
  const hasAvatar = !!preview;

  return (
    <div className={cn('flex flex-col items-center gap-4', className)}>
      {/* Avatar Preview */}
      <div
        className={cn(
          'relative rounded-full border-2 border-dashed transition-all cursor-pointer overflow-hidden',
          sizeClass,
          dragActive && 'border-primary bg-primary/5 scale-105',
          disabled && 'opacity-50 cursor-not-allowed',
          !disabled && !isUploading && 'hover:border-primary/50',
          isUploading && 'cursor-wait',
        )}
        onDragEnter={handleDrag}
        onDragLeave={handleDrag}
        onDragOver={handleDrag}
        onDrop={handleDrop}
        onClick={handleClick}
      >
        {preview ? (
          <img
            src={preview}
            alt="Avatar preview"
            className="w-full h-full object-cover"
          />
        ) : (
          <div className="w-full h-full flex items-center justify-center bg-muted">
            <User className="h-8 w-8 text-muted-foreground" />
          </div>
        )}

        {/* Upload overlay */}
        {!disabled && !isUploading && (
          <div className="absolute inset-0 bg-black/50 opacity-0 hover:opacity-100 transition-opacity flex items-center justify-center">
            <Upload className="h-6 w-6 text-white" />
          </div>
        )}

        {/* Loading overlay */}
        {isUploading && (
          <div className="absolute inset-0 bg-black/50 flex items-center justify-center">
            <Loader2 className="h-6 w-6 text-white animate-spin" />
          </div>
        )}
      </div>

      {/* File input */}
      <input
        ref={fileInputRef}
        type="file"
        accept={accept}
        onChange={handleFileInput}
        disabled={disabled || isUploading}
        className="hidden"
      />

      {/* Actions */}
      <div className="flex flex-col items-center gap-2">
        {!hasAvatar && (
          <Button
            type="button"
            variant="outline"
            size="sm"
            onClick={handleClick}
            disabled={disabled || isUploading}
          >
            <Upload className="h-4 w-4 mr-2" />
            Cliquez pour uploader
          </Button>
        )}

        {hasAvatar && (
          <div className="flex gap-2">
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={handleClick}
              disabled={disabled || isUploading}
            >
              <Upload className="h-4 w-4 mr-2" />
              Changer
            </Button>
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={(e) => {
                e.stopPropagation();
                handleDelete();
              }}
              disabled={disabled || isDeleting}
            >
              {isDeleting ? (
                <Loader2 className="h-4 w-4 mr-2 animate-spin" />
              ) : (
                <X className="h-4 w-4 mr-2" />
              )}
              Supprimer
            </Button>
          </div>
        )}

        <p className="text-xs text-muted-foreground text-center">
          Glissez-déposez une image ou cliquez pour sélectionner
          <br />
          Formats: JPG, PNG, GIF (max {(maxSize / (1024 * 1024)).toFixed(1)}MB)
        </p>
      </div>
    </div>
  );
}
