/// Classe utilitaire pour la validation des champs de formulaire.
///
/// Cette classe fournit des méthodes statiques pour valider différents
/// types de données d'entrée utilisateur.
///
/// **Usage:**
/// ```dart
/// final emailError = Validators.validateEmail(emailController.text);
/// if (emailError != null) {
///   // Afficher l'erreur
/// }
/// ```
class Validators {
  /// Constructeur privé pour empêcher l'instanciation
  Validators._();

  /// Expression régulière pour valider les emails
  static final RegExp _emailRegex = RegExp(
    r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
  );

  /// Expression régulière pour valider les mots de passe forts
  /// (au moins 8 caractères, une majuscule, une minuscule, un chiffre)
  static final RegExp _strongPasswordRegex = RegExp(
    r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$',
  );

  /// Valide une adresse email.
  ///
  /// [value] La valeur à valider
  ///
  /// Returns `null` si l'email est valide, sinon un message d'erreur.
  ///
  /// **Exemple:**
  /// ```dart
  /// final error = Validators.validateEmail('user@example.com');
  /// // Retourne null si valide
  /// ```
  static String? validateEmail(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Veuillez entrer votre email';
    }

    final trimmedValue = value.trim();

    if (!_emailRegex.hasMatch(trimmedValue)) {
      return 'Veuillez entrer un email valide';
    }

    // Validation supplémentaire de la longueur
    if (trimmedValue.length > 254) {
      return 'L\'email est trop long (maximum 254 caractères)';
    }

    return null;
  }

  /// Valide un mot de passe.
  ///
  /// [value] La valeur à valider
  /// [minLength] Longueur minimale requise (par défaut: 6)
  /// [requireStrong] Si true, exige un mot de passe fort (par défaut: false)
  ///
  /// Returns `null` si le mot de passe est valide, sinon un message d'erreur.
  ///
  /// **Exemple:**
  /// ```dart
  /// final error = Validators.validatePassword('password123', minLength: 8);
  /// // Retourne null si valide
  /// ```
  static String? validatePassword(
    String? value, {
    int minLength = 6,
    bool requireStrong = false,
  }) {
    if (value == null || value.isEmpty) {
      return 'Veuillez entrer votre mot de passe';
    }

    if (value.length < minLength) {
      return 'Le mot de passe doit comporter au moins $minLength caractères';
    }

    if (requireStrong && !_strongPasswordRegex.hasMatch(value)) {
      return 'Le mot de passe doit contenir au moins une majuscule, '
          'une minuscule et un chiffre';
    }

    // Validation de la longueur maximale
    if (value.length > 128) {
      return 'Le mot de passe est trop long (maximum 128 caractères)';
    }

    return null;
  }

  /// Valide que deux mots de passe correspondent.
  ///
  /// [password] Le premier mot de passe
  /// [confirmPassword] Le mot de passe de confirmation
  ///
  /// Returns `null` si les mots de passe correspondent, sinon un message d'erreur.
  ///
  /// **Exemple:**
  /// ```dart
  /// final error = Validators.validatePasswordMatch(
  ///   'password123',
  ///   'password123',
  /// );
  /// // Retourne null si correspond
  /// ```
  static String? validatePasswordMatch(String? password, String? confirmPassword) {
    if (password == null || password.isEmpty) {
      return 'Veuillez entrer votre mot de passe';
    }

    if (confirmPassword == null || confirmPassword.isEmpty) {
      return 'Veuillez confirmer votre mot de passe';
    }

    if (password != confirmPassword) {
      return 'Les mots de passe ne correspondent pas';
    }

    return null;
  }

  /// Valide un nom (prénom ou nom de famille).
  ///
  /// [value] La valeur à valider
  /// [fieldName] Le nom du champ (pour le message d'erreur)
  ///
  /// Returns `null` si le nom est valide, sinon un message d'erreur.
  static String? validateName(String? value, {String fieldName = 'ce champ'}) {
    if (value == null || value.trim().isEmpty) {
      return 'Veuillez entrer $fieldName';
    }

    final trimmedValue = value.trim();

    if (trimmedValue.length < 2) {
      return '$fieldName doit contenir au moins 2 caractères';
    }

    if (trimmedValue.length > 100) {
      return '$fieldName est trop long (maximum 100 caractères)';
    }

    // Validation des caractères (lettres, espaces, tirets, apostrophes)
    if (!RegExp(r"^[a-zA-ZÀ-ÿ\s\-']+$").hasMatch(trimmedValue)) {
      return '$fieldName ne doit contenir que des lettres';
    }

    return null;
  }

  /// Valide un numéro de téléphone.
  ///
  /// [value] La valeur à valider
  ///
  /// Returns `null` si le numéro est valide, sinon un message d'erreur.
  static String? validatePhoneNumber(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Veuillez entrer votre numéro de téléphone';
    }

    final trimmedValue = value.trim().replaceAll(RegExp(r'[\s\-\(\)]'), '');

    // Validation du format (10 chiffres pour la France)
    if (!RegExp(r'^\+?[0-9]{10,15}$').hasMatch(trimmedValue)) {
      return 'Veuillez entrer un numéro de téléphone valide';
    }

    return null;
  }

  /// Valide une URL.
  ///
  /// [value] La valeur à valider
  ///
  /// Returns `null` si l'URL est valide, sinon un message d'erreur.
  static String? validateUrl(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Veuillez entrer une URL';
    }

    final trimmedValue = value.trim();

    try {
      final uri = Uri.parse(trimmedValue);
      if (!uri.hasScheme || !uri.hasAuthority) {
        return 'Veuillez entrer une URL valide';
      }
      return null;
    } catch (e) {
      return 'Veuillez entrer une URL valide';
    }
  }

  /// Valide qu'un champ n'est pas vide.
  ///
  /// [value] La valeur à valider
  /// [fieldName] Le nom du champ (pour le message d'erreur)
  ///
  /// Returns `null` si le champ n'est pas vide, sinon un message d'erreur.
  static String? validateRequired(String? value, {String fieldName = 'ce champ'}) {
    if (value == null || value.trim().isEmpty) {
      return 'Veuillez remplir $fieldName';
    }
    return null;
  }

  /// Valide la longueur d'une chaîne.
  ///
  /// [value] La valeur à valider
  /// [minLength] Longueur minimale
  /// [maxLength] Longueur maximale
  /// [fieldName] Le nom du champ (pour le message d'erreur)
  ///
  /// Returns `null` si la longueur est valide, sinon un message d'erreur.
  static String? validateLength(
    String? value, {
    int? minLength,
    int? maxLength,
    String fieldName = 'ce champ',
  }) {
    if (value == null) {
      return 'Veuillez remplir $fieldName';
    }

    final length = value.length;

    if (minLength != null && length < minLength) {
      return '$fieldName doit contenir au moins $minLength caractères';
    }

    if (maxLength != null && length > maxLength) {
      return '$fieldName ne doit pas dépasser $maxLength caractères';
    }

    return null;
  }
}
