# -*- coding: utf-8 -*-
from django import forms
from django.core import validators
from django.core.exceptions import ValidationError
from django.conf import settings
from django.utils.translation import ugettext_lazy as _

import phonenumbers

from events.surveyme.fields.base.validators import validate_phone
from events.surveyme.fields.base.widgets import DateRangeFieldInput, PaymentWidget


class PhoneField(forms.CharField):
    default_country_code = settings.SURVEYME_DEFAULT_PHONE_COUNTRY_CODE

    default_error_messages = {
        'invalid': _('Enter a valid phone.'),
    }
    default_validators = [validate_phone]

    def clean(self, value):
        if value in validators.EMPTY_VALUES and not self.required:
            return value
        value = super(PhoneField, self).clean(value)
        return self._get_formatted_phone_number(value)

    def _get_formatted_phone_number(self, raw_phone_number):
        try:
            phone = phonenumbers.parse(raw_phone_number, settings.SURVEYME_DEFAULT_PHONE_COUNTRY_CODE)
        except phonenumbers.NumberParseException:
            raise ValidationError(self.error_messages['invalid'])
        phone_format = phonenumbers.PhoneNumberFormat.INTERNATIONAL
        if phone.number_of_leading_zeros == 2:
            phone_format = phonenumbers.PhoneNumberFormat.NATIONAL
        return phonenumbers.format_number(phone, phone_format)


class SimpleDateField(forms.DateField):
    def to_python(self, *args, **kwargs):
        value = super(SimpleDateField, self).to_python(*args, **kwargs)
        if not value and self.required:
            raise ValidationError(self.error_messages['required'])
        return {
            'date_start': value,
        }

    def prepare_value(self, value):
        if isinstance(value, dict):
            return value.get('date_start')
        return value


class DateRangeField(forms.MultiValueField):
    widget = DateRangeFieldInput
    default_error_messages = {
        'invalid': _('enter_a_valid_value'),
    }

    def __init__(self, fields=(), *args, **kwargs):
        fields = (
            forms.DateField(),  # date_start
            forms.DateField(),  # date_end
        )
        super(DateRangeField, self).__init__(fields, *args, **kwargs)

    def clean(self, value):
        return super(DateRangeField, self).clean(value)

    def compress(self, data_list):
        if data_list and len(data_list) == 2:
            date_start, date_end = data_list
            return {
                'date_start': date_start,
                'date_end': date_end,
            }
        else:
            return None

    def validate(self, date_range_model):
        self._validate_is_date_start_and_date_end_exists(date_range_model)
        self._validate_is_date_end_after_date_start(date_range_model)

    def _validate_is_date_end_after_date_start(self, date_range_model):
        if date_range_model.get('date_end') < date_range_model.get('date_start'):
            raise ValidationError(_('date_end_earlier_date_start_error'))  # todo: change 216

    def _validate_is_date_start_and_date_end_exists(self, date_range_model):
        if not date_range_model.get('date_start') or not date_range_model.get('date_end'):
            raise ValidationError(self.error_messages['required'])


class PaymentField(forms.CharField):
    widget = PaymentWidget
    min_amount = settings.YOOMONEY_MIN_AMOUNT
    max_amount = settings.YOOMONEY_MAX_AMOUNT

    def _isdigit(self, amount):
        try:
            int(amount)
        except ValueError:
            return False
        return True

    def _validate_amount(self, amount):
        if not self._isdigit(amount):
            raise ValidationError(_('amount_value_must_be_integer'))
        amount = int(amount)
        if amount == 0:
            pass  # считаем, что пользователь хочет отказаться от оплаты
        elif amount < self.min_amount:
            raise ValidationError(_('amount_value_must_be_greather_then_min'))
        elif amount > self.max_amount:
            raise ValidationError(_('amount_value_must_be_less_then_max'))

    def _validate_payment_method(self, payment_method):
        if payment_method not in ('AC', 'PC', 'MC'):
            raise ValidationError(_('incorrect_payment_method_type'))

    def clean(self, value):
        if value in validators.EMPTY_VALUES and not self.required:
            return None

        value = super().clean(value).split(' ')
        if len(value) != 2:
            raise ValidationError(_('incorrect_payment_value'))

        amount, payment_method = value
        self._validate_amount(amount)
        self._validate_payment_method(payment_method)

        return {
            'amount': int(amount),
            'payment_method': payment_method,
        }
