from django.utils.translation import ngettext
from rest_framework.exceptions import ValidationError


class IncludeDigitValidator:
    def __init__(self, message=None):
        self.message = message or 'This field must contain at least 1 digit.'

    def __call__(self, value: str):
        if not any(s.isdigit() for s in value):
            raise ValidationError(self.message)

    def validate(self, value: str, user=None):
        if not any(s.isdigit() for s in value):
            raise ValidationError(self.message)


class IncludeUppercaseValidator:
    def __init__(self, message=None):
        self.message = message or 'This field must contain at least 1 uppercase letter.'

    def __call__(self, value: str):
        if not any(s.isupper() for s in value):
            raise ValidationError(self.message)

    def validate(self, value: str, user=None):
        if not any(s.isupper() for s in value):
            raise ValidationError(self.message)


class IncludeLowercaseValidator:
    def __init__(self, message=None):
        self.message = message or 'This field must contain at least 1 lowercase letter.'

    def __call__(self, value: str):
        if not any(s.islower() for s in value):
            raise ValidationError(self.message)

    def validate(self, value: str, user=None):
        if not any(s.islower() for s in value):
            raise ValidationError(self.message)


class MinimumLengthValidator:
    def __init__(self, min_length, message=None):
        self.min_length = min_length
        self.message = message or self.get_help_text()

    def __call__(self, value):
        if len(value) < self.min_length:
            raise ValidationError(self.message)

    def validate(self, value: str, user=None):
        if len(value) < self.min_length:
            raise ValidationError(self.message)

    def get_help_text(self):
        return (
            ngettext(
                'This field must contain at least %(min_length)d character.',
                'This field must contain at least %(min_length)d characters.',
                self.min_length,
            )
            % {'min_length': self.min_length}
        )


class MaximumLengthValidator:
    def __init__(self, max_length, message=None):
        self.max_length = max_length
        self.message = message or self.get_help_text()

    def __call__(self, value):
        if len(value) > self.max_length:
            raise ValidationError(self.message)

    def validate(self, value: str, user=None):
        if len(value) > self.max_length:
            raise ValidationError(self.message)

    def get_help_text(self):
        return (
            ngettext(
                'This field must contain no more than %(max_length)d character.',
                'This field must contain no more than %(max_length)d characters.',
                self.max_length,
            )
            % {'max_length': self.max_length}
        )
