import traceback
import urllib
from mimetypes import MimeTypes

from django.db.models import FileField
from django.forms import forms
from django.template.defaultfilters import filesizeformat


class RestrictedFileField(FileField):
    def __init__(self, *args, content_types: list = None, max_upload_size=None, **kwargs):
        """
        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
        """

        self.content_types = content_types
        self.max_upload_size = max_upload_size
        super().__init__(*args, **kwargs)

    def clean(self, *args, **kwargs):
        data = super().clean(*args, **kwargs)
        file = data.file

        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 forms.ValidationError('Please keep filesize under %s. Current filesize %s' % (
                    filesizeformat(self.max_upload_size), filesizeformat(file._size)))
            else:
                raise forms.ValidationError('Filetype not supported.')
        except AttributeError:
            raise forms.ValidationError(f'clean Bad file. Change it.\n {traceback.format_exc()}')

        return data

        # if self.content_types:
        #     file_content_type = guess_content_type(file)
        #     if file_content_type not in self.content_types:
        #         raise forms.ValidationError(_('File type not supported. {}').format(file_content_type))
        #
        # if self.max_upload_size and file._size > self.max_upload_size:
        #     raise forms.ValidationError(
        #         _('Please keep filesize under {max_upload_size}. Current filesize {file_size}').format(
        #             max_upload_size=filesizeformat(self.max_upload_size),
        #             file_size=filesizeformat(file._size),
        #         )
        #     )
        #
        # return data

    # def formfield(self, **kwargs):
    #     defaults = {
    #         'form_class': self._get_form_class(),
    #         'content_types': self.content_types,
    #     }
    #     defaults.update(kwargs)
    #     return super().formfield(**defaults)
    #
    # def _get_form_class(self):
    #     return RestrictedFormFileField
