import phonenumbers
import yt.wrapper as yt

from django.conf import settings
from django.core.validators import ValidationError
from django.utils import timezone


class PhoneValidator:
    default_country_code = 'RU'

    def __init__(self, country_code=None):
        self.country_code = country_code or self.default_country_code

    def __call__(self, value):
        try:
            parsed = phonenumbers.parse(value, self.country_code)
        except phonenumbers.NumberParseException as ex:
            message = ex.args[0] if ex.args else 'Phone number is invalid'
            raise ValidationError(message, code='invalid')

        if not phonenumbers.is_valid_number(parsed):
            raise ValidationError('Phone number is invalid', code='invalid')

        if not phonenumbers.is_possible_number(parsed):
            raise ValidationError('Phone number is impossible', code='invalid')


validate_phone = PhoneValidator()


def validate_birthday(birthday):
    if birthday and (birthday.year < 1900 or birthday.year > timezone.now().year):
        raise ValidationError(
            message='invalid',
            code='invalid',
        )


class YTTableValidator:

    def __init__(self, proxy=settings.YT_PROXY):
        self.proxy = proxy

    def __call__(self, path):
        yt.config['token'] = settings.YT_TOKEN
        yt.config['proxy']['url'] = self.proxy
        self._check_path_exists(path)
        self._check_path_is_table(path)

    def _check_path_exists(self, path):
        if not yt.exists(path):
            raise ValidationError(
                message='Path does not exist',
                code='path_does_not_exist',
            )

    def _check_path_is_table(self, path):
        try:
            attributes = yt.get(f'{path}/@', attributes=['type'])
        except yt.YtHttpResponseError as exc:
            if exc.is_access_denied():
                raise ValidationError(
                    message='Access denied',
                    code='access_denied',
                )
            else:
                raise ValidationError(
                    message='Unknown YT error',
                    code='unknown_yt_error',
                )
        if attributes.get('type') != 'table':
            raise ValidationError(
                message='Path is not a table',
                code='path_not_table',
            )


validate_yt_table = YTTableValidator()


def validate_at_least_one_filled(data, fields):
    if not any(data.get(f) is not None for f in fields):
        raise ValidationError(
            message='Specify one of required fields: {}'.format(', '.join(fields)),
            code='at_least_one_field_should_be_filled',
            params={'required_fields': fields},
        )
