from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect, HttpRequest
from django.shortcuts import redirect, get_object_or_404
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import ListView
from django.views.generic.detail import SingleObjectMixin
from jsonrpc import JSONRPCResponseManager

from bots.models import TelegramBot
from bots.modules import BOT_MODULES
from bots.utils import BaseBotConfigView, JSONResponseMixin, AjaxResponseMixin
from cabinet.utils import CabinetViewMixin


class BotListView(CabinetViewMixin, ListView):
    template_name = 'cabinet/bots/bot_list.html'
    title = 'Bot list'
    sidebar_section = 'bots'

    def get_queryset(self):
        return TelegramBot.objects.filter(owner=self.request.user)

    def get_context_data(self, *args, **kwargs):
        ctx = super(BotListView, self).get_context_data(*args, **kwargs)
        ctx['bot_modules'] = BOT_MODULES
        return ctx


class BotConfigEditView(BaseBotConfigView, SingleObjectMixin):
    title = 'Configure bot'
    sidebar_section = 'bots'

    def form_valid(self, bot_form, config_form):
        bot_form.save()
        config_form.save()
        if hasattr(self.model, 'form_valid'):
            self.model.form_valid(self, bot_form, config_form)
        cache.set('bots_reset', '1')
        messages.success(self.request, 'Config was successfully saved')
        return HttpResponseRedirect('')

    def get_content_type(self):
        return self.get_object().config_type


class BotConfigCreateView(BaseBotConfigView):
    title = 'Create bot'
    sidebar_section = 'bots'

    def get_object(self):
        return None

    def form_valid(self, bot_form, config_form):
        config_form.save()
        bot_form.instance.owner = self.request.user
        bot_form.instance.config_type = self.get_content_type()
        bot_form.instance.config_id = config_form.instance.pk
        bot_form.save()
        if hasattr(self.model, 'form_valid'):
            self.model.form_valid(self, bot_form, config_form)
        cache.set('bots_reset', '1')
        messages.success(self.request, 'Config was successfully saved')
        return redirect('cabinet:bots:edit', pk=bot_form.instance.pk)

    def get_content_type(self):
        return get_object_or_404(ContentType, model=self.kwargs['content_type'])


class BotConfigDeleteView(LoginRequiredMixin, SingleObjectMixin, View):
    def get_queryset(self):
        return TelegramBot.objects.filter(owner=self.request.user)

    def post(self, request, *args, **kwargs):
        feed = self.get_object()
        messages.success(self.request, 'Bot "{}" was successfully deleted'.format(feed.title))
        feed.delete()
        return redirect('cabinet:bots:index')


class BotRPCView(JSONResponseMixin, AjaxResponseMixin, View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request: HttpRequest, *args, **kwargs):
        bot = get_object_or_404(TelegramBot, rpc_name=self.kwargs.get('endpoint'))
        if not hasattr(bot.config, 'rpc_dispatcher'):
            raise PermissionDenied()
        rpc_response = JSONRPCResponseManager.handle(request.body, bot.config.rpc_dispatcher)
        response = self.render_json_response(rpc_response.data)
        return response
