from urllib.parse import urlparse

import django_tables2
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.utils.translation import gettext_lazy as _
# Create your views here.
from django.views.generic import ListView, CreateView, TemplateView, UpdateView, FormView
from django_filters.views import FilterView
from django_tables2.export import ExportMixin

from customrolepermissions.permissions import has_permission_exactly
from utils.date_utils import get_date_range_kwargs_from_request, normalize_date_range
from extra_views import CreateWithInlinesView, NamedFormsetsMixin

class Dashboard(LoginRequiredMixin, TemplateView):
    page_header = 'Dashboard'
    template_name = 'theme_one.html'


class BackUrlMixin:
    request = None
    back_url = None
    back_url_inline_visible = False

    @property
    def get_back_url(self):
        # in normal case back_url is hidden in ?inline=t pages. set back_url_inline_visible=True to show.
        if self.back_url and (self.back_url_inline_visible or not self.request.GET.get('inline')):
            return self.back_url + self.get_referer_querystrings()
        return None

    def get_referer_querystrings(self):
        referer = self.request.META.get('HTTP_REFERER')
        querystring = ''
        if referer:
            url = urlparse(referer)
            if url.query:
                querystring = '?{}'.format(url.query)
        if querystring == '':
            url = urlparse(self.request.get_full_path())
            if url.query:
                querystring = '?{}'.format(url.query)
        return querystring


class GenericExportMixin(ExportMixin):
    export_key = None  # set it to enable table export
    request = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.export_key:
            self.export_trigger_param = '_export_{}'.format(self.export_key.replace('-', '_'))

    def get_table(self, **kwargs):
        table = super().get_table(**kwargs)
        if self.export_key and has_permission_exactly(self.request.user, 'dashboard_export_lists'):
            table.table_export = {
                'type': 'xls',
                'label': _('Export as XLS'),
                'css_class': 'mdi mdi-file-excel',
                'export_param': self.export_trigger_param,
            }
        return table

    @property
    def export_name(self):
        date_range = get_date_range_kwargs_from_request(self.request)
        start_date, end_date = normalize_date_range(**date_range)
        return '{}-{:%Y%m%d}-to-{:%Y%m%d}'.format(self.export_key, start_date, end_date)


class GenericListView(LoginRequiredMixin, BackUrlMixin, GenericExportMixin, django_tables2.SingleTableMixin, ListView):
    template_name = 'generic_views/filter_list_view.html'
    add_url = None
    delete_url = None
    update_url = None
    fix_paginate_by = None
    dashboard_layout = None
    ordering = ('-id',)

    @property
    def page_header(self):
        return '%s List' % self.model._meta.verbose_name_plural

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(GenericListView, self).get_context_data(object_list=object_list, **kwargs)
        context['delete_url'] = self.delete_url
        context['update_url'] = self.update_url
        return context

    @property
    def paginate_by(self):
        if self.fix_paginate_by:
            return self.fix_paginate_by
        per_page = self.request.GET.get('per_page')
        if not per_page:
            per_page = self.request.session.get('per_page')
        try:
            per_page = int(per_page)
        except (ValueError, TypeError):
            per_page = 10
        self.request.session['per_page'] = per_page
        return per_page


class GenericFilterListView(LoginRequiredMixin, BackUrlMixin, GenericExportMixin, django_tables2.SingleTableMixin,
                            FilterView):
    template_name = 'generic_views/filter_list_view.html'
    delete_url = None
    update_url = None
    fix_paginate_by = None
    dashboard_layout = None
    extra_js = None
    ordering = ('-id',)

    @property
    def page_header(self):
        return '%s List' % self.model._meta.verbose_name_plural

    def get_queryset(self):
        query = super().get_queryset()
        if self.filterset_class:
            query = self.filterset_class(self.request.GET, queryset=query).qs
        return query

    def get_context_data(self, *args, **kwargs):
        context = super(GenericFilterListView, self).get_context_data(*args, **kwargs)
        context['delete_url'] = self.delete_url
        context['update_url'] = self.update_url
        context['extra_js'] = self.extra_js
        return context

    @property
    def paginate_by(self):
        if self.fix_paginate_by:
            return self.fix_paginate_by
        per_page = self.request.GET.get('per_page')
        if not per_page:
            per_page = self.request.session.get('per_page')
        try:
            per_page = int(per_page)
        except (ValueError, TypeError):
            per_page = 10
        self.request.session['per_page'] = per_page
        return per_page


class GenericCreateView(LoginRequiredMixin, BackUrlMixin, CreateView):
    template_name = 'generic_views/create_view.html'
    title = None

    @property
    def page_header(self):
        return 'Create new %s' % self.model._meta.verbose_name

    def form_valid(self, form):
        # account = Account.objects.filter(user=self.request.user)
        # if account is None:
        #     raise PermissionDenied('You have not Account')
        # form.instance.creator = account.first()
        return super(GenericCreateView, self).form_valid(form)


class GenericCreateTableView(LoginRequiredMixin, BackUrlMixin, CreateView, django_tables2.SingleTableMixin):
    template_name = 'generic_views/create_list_view.html'

    @property
    def page_header(self):
        return 'Create new %s' % self.model._meta.verbose_name


class GenericInlineCreateView(LoginRequiredMixin, BackUrlMixin, NamedFormsetsMixin, CreateWithInlinesView):
    template_name = 'generic_views/create_inline_view.html'

    @property
    def page_header(self):
        return _('Create new %s') % self.model._meta.verbose_name


class GenericUpdateView(LoginRequiredMixin, BackUrlMixin, SuccessMessageMixin, UpdateView):
    template_name = 'generic_views/create_view.html'
    title = None

    @property
    def page_header(self):
        return 'Update %s' % self.model._meta.verbose_name

    # def form_valid(self, form):
    #     return super().form_valid(form)


class GenericUpdateView2(BackUrlMixin, SuccessMessageMixin, UpdateView):
    template_name = 'generic_views/create_view.html'
    title = None

    @property
    def page_header(self):
        return 'Update %s' % self.model._meta.verbose_name

    # def form_valid(self, form):
    #     return super().form_valid(form)


class GenericFormView(LoginRequiredMixin, BackUrlMixin, FormView):
    template_name = 'generic_views/create_view.html'
    title = None

    @property
    def page_header(self):
        return 'Form'


class GenericFormTableView(LoginRequiredMixin, BackUrlMixin, django_tables2.SingleTableMixin, FormView):
    template_name = 'generic_views/create_list_view.html'
    title = None
    fix_paginate_by = None

    @property
    def page_header(self):
        return 'Form'

    @property
    def paginate_by(self):
        if self.fix_paginate_by:
            return self.fix_paginate_by
        per_page = self.request.GET.get('per_page')
        if not per_page:
            per_page = self.request.session.get('per_page')
        try:
            per_page = int(per_page)
        except (ValueError, TypeError):
            per_page = 10
        self.request.session['per_page'] = per_page
        return per_page
