from django.shortcuts import render,get_object_or_404,redirect
from django.urls import reverse, reverse_lazy
from django.http import HttpRequest,HttpResponse,Http404
from django.contrib.auth.mixins import LoginRequiredMixin,UserPassesTestMixin
from django.core.exceptions import PermissionDenied

from django.utils.translation import gettext as _

from .. import settings

from ..models import Page
from .base import View,FormView
from ..forms import PageForm,PageAdminForm,PageDeleteForm

class PageView(View):
    template_name = "tinywiki/page/view.html"
    bs_template_name = "tinywiki/page/bs-view.html"
    
    @classmethod
    def get_template_name(cls) -> str:
        if settings.USE_BOOTSTRAP:
            return cls.bs_template_name
        return cls.template_name
    
    def get_context_data(self,page,**kwargs):
        can_edit_page = False
        can_delete_page = False
        user = self.request.user
        if (user.is_staff):
            can_edit_page = True
            can_delete_page = True
        elif page.slug.startswith('tw-'):
            if user.has_perm('page.tinywiki-edit-system'):
                can_edit_page = True
            if user.has_perm('page.tinywiki-delete-system'):
                can_delete_page = True
        else:
            if (user.has_perm('page.tinywiki-edit-all')
                or (user.pk == page.author.pk and user.has_perm('page.tinywiki-edit'))):
                can_edit_page = True
            if (user.has_perm('page.tinywiki-delete-all')
                or (user.pk == page.author.pk and user.has_perm('page.tinywiki-delete'))):
                can_delete_page = True
            
        kwargs.update({'page':page,
                       'user_can_edit_wiki_page':can_edit_page,
                       'user_can_delete_wiki_page':can_delete_page,
                       'subtitle':page.title})
        return super().get_context_data(**kwargs)
        
    
    def get(self,request:HttpRequest,slug:str)->HttpResponse:
        try:
            page = Page.objects.get(slug=slug)
        except Page.DoesNotExist:
            if self.page_is_creatable(slug):
                return redirect(reverse('tinywiki:page-create') + f"?slug={slug}")
            raise Http404()
        return render(request,
                      self.get_template_name(),
                      self.get_context_data(page=page))
        
class PageCreateView(LoginRequiredMixin,UserPassesTestMixin,FormView):
    template_name = "tinywiki/page/create.html"
    bs_template_name = "tinywiki/page/bs-create.html"
    form_class = PageForm
    
    def test_func(self) -> bool:
        if self.request.user.is_authenticated:
            if self.request.user.is_staff:
                return True
            return self.request.user.has_perm('tinywiki.tinywiki-create')
        return False
    
    def get_template_name(self) -> str:
        if settings.USE_BOOTSTRAP:
            return self.bs_template_name
        return self.template_name
    
    def get(self,request):
        return render(request,
                      self.get_template_name(),
                      self.get_context_data())
        
    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        context['create']=True
        context['slug'] = self.request.GET.get('slug',None)
        context.setdefault("title_extra","")
        context.setdefault("slug_extra","")
        context.setdefault("content_type_extra","")
        context.setdefault("status_extra","")
        context.setdefault("content_extra","")
        
        return context
        
    def form_invalid(self, form):
        if 'slug' in form.errors:
            slug_extra = "is-invalid"
        else:
            slug_extra = "is-valid"
            
        if 'title' in form.errors:
            title_extra = 'is-invalid'
        else:
            title_extra = 'is-valid'
            
        if 'status_data' in form.errors:
            status_extra = 'is-invalid'
        else:
            status_extra = 'is-valid'
            
        if 'content_type_data' in form.errors:
            content_type_extra = 'is-invalid'
        else:
            content_type_extra = 'is-valid'
            
        if 'content' in form.errors:
            content_extra = 'is-invalid'
        else:
            content_extra = 'is-valid'
            
        return render(self.request,
                      self.get_template_name(),
                      self.get_context_data(
                          slug_extra=slug_extra,
                          title_extra=title_extra,
                          status_extra=status_extra,
                          content_type_extra=content_type_extra,
                          content_extra=content_extra,
                      ))
        
    def form_valid(self,form):
        user = self.request.user
        instance = form.save(commit=False)
        if (instance.slug.startswith('tw-') 
            and not user.is_staff and 
            not user.has_perm('page.tinywiki-create-system')):
            return render(self.request,
                          self.get_template_name(),
                          self.get_context_data(
                            slug_extra="is-invalid",
                            title_extra="is-valid",
                            status_extra="is-valid",
                            content_type_extra="is-valid",
                            content_extra="is-valid",
                          ))
        
        instance.author = user
        instance.created_by = user
        instance.last_edited_by = user
        try:
            form.save(commit=True)
            if self.request.GET.get('save',"0") == "1":
                return redirect(reverse("tinywiki:page-edit",kwargs={"slug":instance.slug}))
            return redirect(reverse("tinywiki:page",kwargs={'slug':instance.slug}))
        except:
            return render(self.request,
                          self.get_template_name(),
                          self.get_context_data(
                              slug_extra="is-invalid",
                              title_extra="is-valid",
                              status_extra="is-valid",
                              content_type_extra="is-valid",
                              content_extra="is-valid",
                          ))
        

class PageEditView(LoginRequiredMixin,UserPassesTestMixin,FormView):
    template_name = "tinywiki/page/edit.html"
    bs_template_name = "tinywiki/page/bs-edit.html"
    form_class = PageForm
    
    def test_func(self) -> bool:
        if self.request.user.is_authenticated:
            if self.request.user.is_staff:
                return True
        return False
    
    def get_template_name(self) -> str:
        if settings.USE_BOOTSTRAP:
            return self.bs_template_name
        return self.template_name
    
    def get_context_data(self,page,**kwargs):
        context = super().get_context_data(**kwargs)
        context['create']=False
        context['page']=page
        context.setdefault("title_extra","")
        context.setdefault("slug_extra","")
        context.setdefault("content_type_extra","")
        context.setdefault("status_extra","")
        context.setdefault("content_extra","")
        return context
        
    def form_invalid(self, form):
        if 'slug' in form.errors:
            slug_extra = "is-invalid"
        else:
            slug_extra = "is-valid"
            
        if 'title' in form.errors:
            title_extra = 'is-invalid'
        else:
            title_extra = 'is-valid'
            
        if 'status_data' in form.errors:
            status_extra = 'is-invalid'
        else:
            status_extra = 'is-valid'
            
        if 'content_type_data' in form.errors:
            content_type_extra = 'is-invalid'
        else:
            content_type_extra = 'is-valid'
            
        if 'content' in form.errors:
            content_extra = 'is-invalid'
        else:
            content_extra = 'is-valid'
            
        return render(self.request,
                      self.get_template_name(),
                      self.get_context_data(
                          page=self.instance,
                          slug_extra=slug_extra,
                          title_extra=title_extra,
                          status_extra=status_extra,
                          content_type_extra=content_type_extra,
                          content_extra=content_extra,
                      ))
    
    def get(self,request,slug:str):
        instance = get_object_or_404(Page,slug=slug)
        user = request.user
        if (instance.slug.startswith('tw-') 
            and not user.is_staff
            and not user.has_perm('page.tinywiki-edit-system')):
            raise PermissionDenied(_("Only staff users and wiki-admins are allowed to edit TinyWiki system pages!"))
        
        if user.pk != instance.author.pk:
            if not user.is_staff and not user.has_perm("page.tinywiki-edit-all"):
                raise PermissionDenied()
        else:
            if not user.has_perm('page.tinywiki-edit-all') or not user.has_perm('page.tinywiki-edit'):
                raise PermissionDenied()
            
        self.instance = instance
        
        return render(request,
                      self.get_template_name(),
                      self.get_context_data(page=instance))
    
    def post(self,request,slug:str):
        instance = get_object_or_404(Page,slug=slug)
        user = request.user
        if (instance.slug.startswith('tw-') and not user.is_staff):
            raise PermissionDenied(_("Only staff users are allowed to edit TinyWiki system pages!"))
        
        if user.pk != instance.author.pk:
            if not user.is_staff and not user.has_perm("page.tinywiki-edit-all"):
                raise PermissionDenied()
        else:
            if not user.has_perm('page.tinywiki-edit-all') or not user.has_perm('page.tinywiki-edit'):
                raise PermissionDenied()
            
        self.instance = instance
        
        return super().post(request)
    
    def get_form(self):
        return self.get_form_class()(instance=self.instance,**self.get_form_kwargs())
    
    def form_valid(self,form):
        user = self.request.user
        instance = form.save(commit=False)
        instance.created_by = user
        instance.last_edited_by = user
        try:
            form.save(commit=True)
            if self.request.GET.get('save',"0") == "1":
                return redirect(reverse("tinywiki:page-edit",kwargs={"slug":instance.slug}))
            return redirect(reverse("tinywiki:page",kwargs={'slug':instance.slug}))
        except:
            return render(self.request,
                          self.get_template_name(),
                          self.get_context_data(slug_invalid=True))
            
class PageDeleteView(LoginRequiredMixin,UserPassesTestMixin,FormView):
    template_name = "tinywiki/page/delete.html"
    form_class = PageDeleteForm
    def test_func(self) -> bool:
        if self.request.user.is_staff:
            return True
        if self.request.user.has_perm('tinyiwki-delete-all') or self.request.user.has_perm('tinywiki-delete'):
            return True
        return False
    
    def get(self,request:HttpRequest,slug:str)->HttpResponse:
        instance = get_object_or_404(Page,slug=slug)
        if not request.user.is_staff and not instance.author == request.user:
            raise PermissionDenied()
        
        return render(request,
                      self.template_name,
                      self.get_context_data(form=self.get_form_class()(),
                                            page=instance))
        
    def form_invalid(self,form:PageDeleteForm)->HttpResponse:
        return redirect(reverse('tinywiki:page',kwargs={'slug':self.instance.slug}))
    
    def form_valid(self,form:PageDeleteForm)->HttpResponse:
        if self.instance.slug == form.cleaned_data['slug']:
            try:
                self.instance.delete()
                return redirect(reverse("tinywiki:home"))
            except: pass
        return redirect(reverse('tinywiki:page',kwargs={'slug':self.instance.slug}))
    
        
    def post(self,request:HttpRequest,slug:str)->HttpResponse:
        self.instance = get_object_or_404(Page,slug=slug)
        if not request.user.is_staff and not instance.author == request.user:
            raise PermissionDenied()
        return super().post(request)
        
    
class HxPageEditView(LoginRequiredMixin,UserPassesTestMixin,FormView):
    template_name = "tinywiki/page/hx-edit.html"
    bs_template_name = "tinywiki/page/hx-bs-edit.html"
    form_class = PageForm
    
    def test_func(self) -> bool:
        if self.request.user.is_authenticated:
            if self.request.user.is_staff:
                return True
            if self.request.user.has_perm('tinywiki-edit-page') or self.request.user.has_perm('tinywiki-edit-all-pages'):
                return True
        return False
    
    def get_template_name(self) -> str:
        if settings.USE_BOOTSTRAP:
            return self.bs_template_name
        return self.template_name
    
    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        context['create']=False
        context['page']=self.instance
        context.setdefault("title_extra","")
        context.setdefault("slug_extra","")
        context.setdefault("content_type_extra","")
        context.setdefault("status_extra","")
        context.setdefault("content_extra","")
        return context
        
    def form_invalid(self, form):
        if 'slug' in form.errors:
            slug_extra = "is-invalid"
        else:
            slug_extra = "is-valid"
            
        if 'title' in form.errors:
            title_extra = 'is-invalid'
        else:
            title_extra = 'is-valid'
            
        if 'status_data' in form.errors:
            status_extra = 'is-invalid'
        else:
            status_extra = 'is-valid'
            
        if 'content_type_data' in form.errors:
            content_type_extra = 'is-invalid'
        else:
            content_type_extra = 'is-valid'
            
        if 'content' in form.errors:
            content_extra = 'is-invalid'
        else:
            content_extra = 'is-valid'
            
        return render(self.request,
                      self.get_template_name(),
                      self.get_context_data(
                          page=self.instance,
                      ))
    
    def post(self,request,pk:int):
        instance = get_object_or_404(Page,pk=pk)
        user = request.user
        if (instance.slug.startswith('tw-') and not user.is_staff):
            raise PermissionDenied(_("Only staff users are allowed to edit TinyWiki system pages!"))
        
        if user.pk != instance.author.pk:
            if not user.is_staff and not user.has_perm("page.tinywiki-edit-all"):
                raise PermissionDenied()
        else:
            if not user.has_perm('page.tinywiki-edit-all') or not user.has_perm('page.tinywiki-edit'):
                raise PermissionDenied()
            
        self.instance = instance
        
        return super().post(request)
    
    def get_form(self):
        return self.get_form_class()(instance=self.instance,**self.get_form_kwargs())
    
    def form_valid(self,form):
        user = self.request.user
        instance = form.save(commit=False)
        instance.created_by = user
        instance.last_edited_by = user
        try:
            form.save(commit=True)
            return render(self.request,self.get_template_name(),self.get_context_data(save_success=True))
        except:
            return render(self.request,
                          self.get_template_name(),
                          self.get_context_data(save_success=False))

class HxPageDeleteView(View):
    pass