#
import traceback
import urllib
from mimetypes import MimeTypes

from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.template.defaultfilters import filesizeformat
from django.utils.functional import lazy
from django.utils.translation import get_language, gettext_lazy as _

from .date_utils import get_date_formats, start_of_day

fmt = get_date_formats()

MIN_DATE = getattr(settings, 'MIN_DATE', None)
MIN_DATETIME = start_of_day(MIN_DATE) if MIN_DATE else None


class DatePickerMedia:
    css = {
        'screen': [
            # 'vendor/air-datepicker/css/datepicker.min.css',
            'vendor/persian-datepicker/css/persian-datepicker.min.css',
        ],
    }
    js = [
        # 'vendor/air-datepicker/js/datepicker.min.js',
        # 'vendor/air-datepicker/js/i18n/datepicker.en.js',
        # 'vendor/air-datepicker/js/auto-datepicker.js',
        'vendor/persian-datepicker/js/persian-date.min.js',
        'vendor/persian-datepicker/js/persian-datepicker.min.js',
        'vendor/persian-datepicker/js/auto-persian-datepicker.js',
    ]


class DatePickerInput(forms.DateInput):
    class Media(DatePickerMedia):
        pass

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.attrs.update({
            'placeholder': fmt.DATE_PLACEHOLDER,
            'class': 'auto-datepicker',
            'data-date-format': fmt.DATE_INPUT_FORMAT,
            'data-auto-close': 'true',
            'data-first-day': 1,
            'data-language': lazy(lambda: get_language())(),
            'autocomplete': 'off',
        })


def validate_min_date(value):
    if value and value < MIN_DATE:
        raise ValidationError(_('Enter a valid date'), code='invalid')


def validate_min_datetime(value):
    if value and value < MIN_DATETIME:
        raise ValidationError(_('Enter a valid date'), code='invalid')


class DatePickerField(forms.DateField):
    widget = DatePickerInput
    default_validators = [validate_min_date] if MIN_DATE else []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if not self.required:
            self.widget.attrs.update({
                'data-clear-button': 'true',
            })


class DateTimePickerInput(forms.DateTimeInput):
    class Media(DatePickerMedia):
        pass

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.attrs.update({
            'placeholder': fmt.DATETIME_PLACEHOLDER,
            'class': 'auto-datepicker',
            'data-date-format': fmt.DATE_INPUT_FORMAT,
            'data-time-format': fmt.TIME_INPUT_FORMAT,
            'data-timepicker': 'true',
            'data-auto-close': 'true',
            'data-first-day': 1,
            'data-language': lazy(lambda: get_language())(),
            'autocomplete': 'off',
        })


class DateTimePickerField(forms.DateTimeField):
    widget = DateTimePickerInput
    default_validators = [validate_min_datetime] if MIN_DATE else []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if not self.required:
            self.widget.attrs.update({
                'data-clear-button': 'true',
            })


class RestrictedFormFileField(forms.FileField):
    """
    Same as FileField, but you can specify:
    * content_types - list containing allowed content_types. Example: ['application/pdf', 'image/jpeg']
    * max_upload_size - a number indicating the maximum file size allowed for upload.
        2.5MB - 2621440
        5MB - 5242880
        10MB - 10485760
        20MB - 20971520
        50MB - 5242880
        100MB - 104857600
        250MB - 214958080
        500MB - 429916160
"""

    def __init__(self, *args, **kwargs):
        self.content_types = kwargs.pop("content_types")
        self.max_upload_size = kwargs.pop("max_upload_size")

        super().__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        file = super().clean(data, initial)

        try:
            if hasattr(file, 'content_type'):
                content_type = file.content_type
            else:
                mime = MimeTypes()
                url = urllib.request.pathname2url(file.name)
                content_type = mime.guess_type(url)[0]
            if content_type in self.content_types:
                if file.size > self.max_upload_size:
                    raise ValidationError(_('Please keep filesize under %s. Current filesize %s') % (
                        filesizeformat(self.max_upload_size), filesizeformat(file._size)))
            else:
                raise ValidationError(_('Filetype not supported.'))
        except AttributeError:
            raise forms.ValidationError(f'Bad file. Change it.\n{traceback.format_exc()}')

        return data
