class AppValidators {
  AppValidators._();

  static String? required(
    String value, {
    String message = 'Field tidak boleh kosong',
  }) {
    if (value.trim().isEmpty) {
      return message;
    }
    return null;
  }

  static String? minLength(
    String value,
    int min, {
    String? message,
  }) {
    if (value.length < min) {
      return message ?? 'Minimal $min karakter';
    }
    return null;
  }

  static String? maxLength(
    String value,
    int max, {
    String? message,
  }) {
    if (value.length > max) {
      return message ?? 'Maksimal $max karakter';
    }
    return null;
  }

  static final _emailRegex = RegExp(r'^[\w\.-]+@([\w-]+\.)+[\w-]{2,}$');

  static String? email(
    String value, {
    String emptyMessage = 'Email tidak boleh kosong',
    String invalidMessage = 'Format email tidak valid',
  }) {
    if (value.trim().isEmpty) {
      return emptyMessage;
    }

    if (!_emailRegex.hasMatch(value.trim())) {
      return invalidMessage;
    }

    return null;
  }

  static final _phoneRegex = RegExp(r'^[0-9]{9,15}$');

  static String? phone(
    String value, {
    String emptyMessage = 'Nomor telepon tidak boleh kosong',
    String invalidMessage = 'Nomor telepon tidak valid',
  }) {
    final v = value.replaceAll(RegExp('[^0-9]'), '');

    if (v.isEmpty) {
      return emptyMessage;
    }

    if (!_phoneRegex.hasMatch(v)) {
      return invalidMessage;
    }

    return null;
  }

  static String? password(
    String value, {
    int minLength = 8,
    bool requireUppercase = true,
    bool requireNumber = true,
    bool requireSymbol = false,
  }) {
    if (value.isEmpty) {
      return 'Password tidak boleh kosong';
    }

    if (value.length < minLength) {
      return 'Password minimal $minLength karakter';
    }

    if (requireUppercase && !value.contains(RegExp('[A-Z]'))) {
      return 'Password harus mengandung huruf besar';
    }

    if (requireNumber && !value.contains(RegExp('[0-9]'))) {
      return 'Password harus mengandung angka';
    }

    if (requireSymbol && !value.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'))) {
      return 'Password harus mengandung simbol';
    }

    return null;
  }

  static String? number(
    String value, {
    String message = 'Harus berupa angka',
  }) {
    if (value.isEmpty) return null;

    if (num.tryParse(value) == null) {
      return message;
    }

    return null;
  }

  static String? minNumber(
    String value,
    num min, {
    String? message,
  }) {
    final n = num.tryParse(value);
    if (n == null) return 'Harus berupa angka';

    if (n < min) {
      return message ?? 'Minimal $min';
    }
    return null;
  }

  static String? maxNumber(
    String value,
    num max, {
    String? message,
  }) {
    final n = num.tryParse(value);
    if (n == null) return 'Harus berupa angka';

    if (n > max) {
      return message ?? 'Maksimal $max';
    }
    return null;
  }

  static String? equals(
    String value,
    String otherValue, {
    String message = 'Nilai tidak sama',
  }) {
    if (value != otherValue) {
      return message;
    }
    return null;
  }

  static String? compose(
    String value,
    List<String? Function(String)> validators,
  ) {
    for (final validator in validators) {
      final result = validator(value);
      if (result != null) return result;
    }
    return null;
  }
}
