/// Form Validators for Vietnamese Locale
///
/// Provides validation utilities for forms with Vietnamese-specific
/// validations for phone numbers, email, passwords, etc.
library;

/// Form field validators
class Validators {
  Validators._();

  // ========================================================================
  // Required Field Validators
  // ========================================================================

  /// Validate required field
  static String? required(String? value, {String? fieldName}) {
    if (value == null || value.trim().isEmpty) {
      return fieldName != null
          ? '$fieldName là bắt buộc'
          : 'Trường này là bắt buộc';
    }
    return null;
  }

  // ========================================================================
  // Phone Number Validators
  // ========================================================================

  /// Validate Vietnamese phone number
  ///
  /// Accepts formats:
  /// - 0xxx xxx xxx (10 digits starting with 0)
  /// - +84xxx xxx xxx (starts with +84)
  /// - 84xxx xxx xxx (starts with 84)
  static String? phone(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập số điện thoại';
    }

    final cleaned = value.replaceAll(RegExp(r'\D'), '');

    // Check if starts with valid Vietnamese mobile prefix
    final vietnamesePattern = RegExp(r'^(0|\+?84)(3|5|7|8|9)[0-9]{8}$');

    if (!vietnamesePattern.hasMatch(value.replaceAll(RegExp(r'[^\d+]'), ''))) {
      return 'Số điện thoại không hợp lệ';
    }

    if (cleaned.length < 10 || cleaned.length > 11) {
      return 'Số điện thoại phải có 10 chữ số';
    }

    return null;
  }

  /// Validate phone number (optional)
  static String? phoneOptional(String? value) {
    if (value == null || value.trim().isEmpty) {
      return null; // Optional, so null is valid
    }
    return phone(value);
  }

  // ========================================================================
  // Email Validators
  // ========================================================================

  /// Validate email address
  static String? email(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập email';
    }

    final emailRegex = RegExp(
      r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
    );

    if (!emailRegex.hasMatch(value)) {
      return 'Email không hợp lệ';
    }

    return null;
  }

  /// Validate email (optional)
  static String? emailOptional(String? value) {
    if (value == null || value.trim().isEmpty) {
      return null;
    }
    return email(value);
  }

  // ========================================================================
  // Password Validators
  // ========================================================================

  /// Validate password strength
  ///
  /// Requirements:
  /// - At least 8 characters
  /// - At least 1 uppercase letter
  /// - At least 1 lowercase letter
  /// - At least 1 number
  /// - At least 1 special character
  static String? password(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập mật khẩu';
    }

    if (value.length < 8) {
      return 'Mật khẩu phải có ít nhất 8 ký tự';
    }

    if (!RegExp(r'[A-Z]').hasMatch(value)) {
      return 'Mật khẩu phải có ít nhất 1 chữ hoa';
    }

    if (!RegExp(r'[a-z]').hasMatch(value)) {
      return 'Mật khẩu phải có ít nhất 1 chữ thường';
    }

    if (!RegExp(r'[0-9]').hasMatch(value)) {
      return 'Mật khẩu phải có ít nhất 1 số';
    }

    if (!RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(value)) {
      return 'Mật khẩu phải có ít nhất 1 ký tự đặc biệt';
    }

    return null;
  }

  /// Validate password confirmation
  static String? confirmPassword(String? value, String? password) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng xác nhận mật khẩu';
    }

    if (value != password) {
      return 'Mật khẩu không khớp';
    }

    return null;
  }

  /// Simple password validator (minimum length only)
  static String? passwordSimple(String? value, {int minLength = 6}) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập mật khẩu';
    }

    if (value.length < minLength) {
      return 'Mật khẩu phải có ít nhất $minLength ký tự';
    }

    return null;
  }

  // ========================================================================
  // OTP Validators
  // ========================================================================

  /// Validate OTP code
  static String? otp(String? value, {int length = 6}) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập mã OTP';
    }

    if (value.length != length) {
      return 'Mã OTP phải có $length chữ số';
    }

    if (!RegExp(r'^[0-9]+$').hasMatch(value)) {
      return 'Mã OTP chỉ được chứa số';
    }

    return null;
  }

  // ========================================================================
  // Text Length Validators
  // ========================================================================

  /// Validate minimum length
  static String? minLength(String? value, int min, {String? fieldName}) {
    if (value == null || value.trim().isEmpty) {
      return fieldName != null
          ? '$fieldName là bắt buộc'
          : 'Trường này là bắt buộc';
    }

    if (value.length < min) {
      return fieldName != null
          ? '$fieldName phải có ít nhất $min ký tự'
          : 'Phải có ít nhất $min ký tự';
    }

    return null;
  }

  /// Validate maximum length
  static String? maxLength(String? value, int max, {String? fieldName}) {
    if (value != null && value.length > max) {
      return fieldName != null
          ? '$fieldName không được vượt quá $max ký tự'
          : 'Không được vượt quá $max ký tự';
    }

    return null;
  }

  /// Validate length range
  static String? lengthRange(
    String? value,
    int min,
    int max, {
    String? fieldName,
  }) {
    if (value == null || value.trim().isEmpty) {
      return fieldName != null
          ? '$fieldName là bắt buộc'
          : 'Trường này là bắt buộc';
    }

    if (value.length < min || value.length > max) {
      return fieldName != null
          ? '$fieldName phải có từ $min đến $max ký tự'
          : 'Phải có từ $min đến $max ký tự';
    }

    return null;
  }

  // ========================================================================
  // Number Validators
  // ========================================================================

  /// Validate number
  static String? number(String? value, {String? fieldName}) {
    if (value == null || value.trim().isEmpty) {
      return fieldName != null
          ? '$fieldName là bắt buộc'
          : 'Trường này là bắt buộc';
    }

    if (double.tryParse(value) == null) {
      return fieldName != null ? '$fieldName phải là số' : 'Giá trị phải là số';
    }

    return null;
  }

  /// Validate integer
  static String? integer(String? value, {String? fieldName}) {
    if (value == null || value.trim().isEmpty) {
      return fieldName != null
          ? '$fieldName là bắt buộc'
          : 'Trường này là bắt buộc';
    }

    if (int.tryParse(value) == null) {
      return fieldName != null
          ? '$fieldName phải là số nguyên'
          : 'Giá trị phải là số nguyên';
    }

    return null;
  }

  /// Validate positive number
  static String? positiveNumber(String? value, {String? fieldName}) {
    final numberError = number(value, fieldName: fieldName);
    if (numberError != null) return numberError;

    final num = double.parse(value!);
    if (num <= 0) {
      return fieldName != null
          ? '$fieldName phải lớn hơn 0'
          : 'Giá trị phải lớn hơn 0';
    }

    return null;
  }

  /// Validate number range
  static String? numberRange(
    String? value,
    double min,
    double max, {
    String? fieldName,
  }) {
    final numberError = number(value, fieldName: fieldName);
    if (numberError != null) return numberError;

    final num = double.parse(value!);
    if (num < min || num > max) {
      return fieldName != null
          ? '$fieldName phải từ $min đến $max'
          : 'Giá trị phải từ $min đến $max';
    }

    return null;
  }

  // ========================================================================
  // Date Validators
  // ========================================================================

  /// Validate date format (dd/MM/yyyy)
  static String? date(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập ngày';
    }

    final dateRegex = RegExp(r'^\d{2}/\d{2}/\d{4}$');
    if (!dateRegex.hasMatch(value)) {
      return 'Định dạng ngày không hợp lệ (dd/MM/yyyy)';
    }

    try {
      final parts = value.split('/');
      final day = int.parse(parts[0]);
      final month = int.parse(parts[1]);
      final year = int.parse(parts[2]);

      final date = DateTime(year, month, day);

      if (date.day != day || date.month != month || date.year != year) {
        return 'Ngày không hợp lệ';
      }
    } catch (e) {
      return 'Ngày không hợp lệ';
    }

    return null;
  }

  /// Validate age (must be at least 18 years old)
  static String? age(String? value, {int minAge = 18}) {
    final dateError = date(value);
    if (dateError != null) return dateError;

    try {
      final parts = value!.split('/');
      final birthDate = DateTime(
        int.parse(parts[2]),
        int.parse(parts[1]),
        int.parse(parts[0]),
      );

      final today = DateTime.now();
      final age =
          today.year -
          birthDate.year -
          (today.month > birthDate.month ||
                  (today.month == birthDate.month && today.day >= birthDate.day)
              ? 0
              : 1);

      if (age < minAge) {
        return 'Bạn phải từ $minAge tuổi trở lên';
      }

      return null;
    } catch (e) {
      return 'Ngày sinh không hợp lệ';
    }
  }

  // ========================================================================
  // Address Validators
  // ========================================================================

  /// Validate Vietnamese address
  static String? address(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập địa chỉ';
    }

    if (value.length < 10) {
      return 'Địa chỉ quá ngắn';
    }

    return null;
  }

  // ========================================================================
  // Tax ID Validators
  // ========================================================================

  /// Validate Vietnamese Tax ID (Mã số thuế)
  /// Format: 10 or 13 digits
  static String? taxId(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập mã số thuế';
    }

    final cleaned = value.replaceAll(RegExp(r'\D'), '');

    if (cleaned.length != 10 && cleaned.length != 13) {
      return 'Mã số thuế phải có 10 hoặc 13 chữ số';
    }

    return null;
  }

  /// Validate tax ID (optional)
  static String? taxIdOptional(String? value) {
    if (value == null || value.trim().isEmpty) {
      return null;
    }
    return taxId(value);
  }

  // ========================================================================
  // URL Validators
  // ========================================================================

  /// Validate URL
  static String? url(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập URL';
    }

    final urlRegex = RegExp(
      r'^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$',
    );

    if (!urlRegex.hasMatch(value)) {
      return 'URL không hợp lệ';
    }

    return null;
  }

  // ========================================================================
  // Combination Validators
  // ========================================================================

  /// Combine multiple validators
  static String? Function(String?) combine(
    List<String? Function(String?)> validators,
  ) {
    return (String? value) {
      for (final validator in validators) {
        final error = validator(value);
        if (error != null) return error;
      }
      return null;
    };
  }

  // ========================================================================
  // Custom Pattern Validators
  // ========================================================================

  /// Validate against custom regex pattern
  static String? pattern(String? value, RegExp pattern, String errorMessage) {
    if (value == null || value.trim().isEmpty) {
      return 'Trường này là bắt buộc';
    }

    if (!pattern.hasMatch(value)) {
      return errorMessage;
    }

    return null;
  }

  // ========================================================================
  // Match Validators
  // ========================================================================

  /// Validate that value matches another value
  static String? match(String? value, String? matchValue, String fieldName) {
    if (value == null || value.trim().isEmpty) {
      return 'Vui lòng nhập $fieldName';
    }

    if (value != matchValue) {
      return '$fieldName không khớp';
    }

    return null;
  }
}

/// Password strength enum
enum PasswordStrength { weak, medium, strong, veryStrong }

/// Password strength calculator
class PasswordStrengthCalculator {
  /// Calculate password strength
  static PasswordStrength calculate(String password) {
    if (password.isEmpty) return PasswordStrength.weak;

    var score = 0;

    // Length check
    if (password.length >= 8) score++;
    if (password.length >= 12) score++;
    if (password.length >= 16) score++;

    // Character variety check
    if (RegExp(r'[a-z]').hasMatch(password)) score++;
    if (RegExp(r'[A-Z]').hasMatch(password)) score++;
    if (RegExp(r'[0-9]').hasMatch(password)) score++;
    if (RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(password)) score++;

    // Return strength based on score
    if (score <= 2) return PasswordStrength.weak;
    if (score <= 4) return PasswordStrength.medium;
    if (score <= 6) return PasswordStrength.strong;
    return PasswordStrength.veryStrong;
  }

  /// Get strength label in Vietnamese
  static String getLabel(PasswordStrength strength) {
    switch (strength) {
      case PasswordStrength.weak:
        return 'Yếu';
      case PasswordStrength.medium:
        return 'Trung bình';
      case PasswordStrength.strong:
        return 'Mạnh';
      case PasswordStrength.veryStrong:
        return 'Rất mạnh';
    }
  }
}
