package dev.lions.exceptions;

import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * Exception spécialisée pour la gestion des erreurs lors du téléchargement de fichiers.
 * Cette classe encapsule les différents types d'erreurs pouvant survenir pendant
 * le processus de téléchargement et de traitement des fichiers.
 *
 * @author Lions Dev Team
 * @version 1.0
 */
@Slf4j
public class FileUploadException extends BusinessException {

  private static final long serialVersionUID = 1L;

  /**
   * Détails techniques de l'erreur de téléchargement
   */
  private final FileUploadErrorDetails errorDetails;

  /**
   * Crée une nouvelle instance avec un message d'erreur simple.
   *
   * @param message Description de l'erreur
   */
  public FileUploadException(String message) {
    this(message, null, null);
    log.error("Erreur de téléchargement : {}", message);
  }

  /**
   * Crée une nouvelle instance avec un message et une cause.
   *
   * @param message Description de l'erreur
   * @param cause Exception à l'origine de l'erreur
   */
  public FileUploadException(String message, Throwable cause) {
    this(message, cause, null);
    log.error("Erreur de téléchargement : {}", message, cause);
  }

  /**
   * Crée une nouvelle instance avec tous les détails de l'erreur.
   *
   * @param message Description de l'erreur
   * @param cause Exception à l'origine de l'erreur
   * @param errorDetails Détails techniques de l'erreur
   */
  public FileUploadException(String message, Throwable cause, FileUploadErrorDetails errorDetails) {
    super(message, cause);
    this.errorDetails = errorDetails;
    log.error("Erreur de téléchargement détaillée : {} - Détails : {}", message, errorDetails);
  }

  /**
   * Récupère les détails techniques de l'erreur.
   *
   * @return Détails de l'erreur ou null si non disponibles
   */
  public FileUploadErrorDetails getErrorDetails() {
    return errorDetails;
  }

  /**
   * Classe interne représentant les détails techniques d'une erreur de téléchargement.
   */
  @Getter
  @Builder
  public static class FileUploadErrorDetails {
    private final String fileName;
    private final long fileSize;
    private final String mimeType;
    private final String uploadLocation;
    private final String validationError;
    private final String processingPhase;

    @Override
    public String toString() {
      return String.format(
          "FileUploadErrorDetails[fileName=%s, fileSize=%d, mimeType=%s, " +
          "location=%s, error=%s, phase=%s]",
          fileName, fileSize, mimeType, uploadLocation, validationError, processingPhase
      );
    }
  }

  /**
   * Crée une instance d'exception pour un fichier trop volumineux.
   *
   * @param fileName Nom du fichier
   * @param actualSize Taille réelle du fichier
   * @param maxSize Taille maximale autorisée
   * @return Instance de FileUploadException
   */
  public static FileUploadException fileTooLarge(String fileName, long actualSize, long maxSize) {
    String message = String.format(
        "Le fichier '%s' est trop volumineux (%d octets). Maximum autorisé : %d octets",
        fileName, actualSize, maxSize
    );

    FileUploadErrorDetails details = FileUploadErrorDetails.builder()
                                                           .fileName(fileName)
                                                           .fileSize(actualSize)
                                                           .validationError("FILE_TOO_LARGE")
                                                           .processingPhase("VALIDATION")
                                                           .build();

    return new FileUploadException(message, null, details);
  }

  /**
   * Crée une instance d'exception pour un type de fichier non autorisé.
   *
   * @param fileName Nom du fichier
   * @param mimeType Type MIME du fichier
   * @return Instance de FileUploadException
   */
  public static FileUploadException invalidFileType(String fileName, String mimeType) {
    String message = String.format(
        "Le type de fichier '%s' n'est pas autorisé pour '%s'",
        mimeType, fileName
    );

    FileUploadErrorDetails details =
        FileUploadErrorDetails.builder().fileName(fileName).mimeType(mimeType)
                              .validationError("INVALID_FILE_TYPE").processingPhase("VALIDATION")
                              .fileSize(-1).build();

    return new FileUploadException(message, null, details);
  }
}