from ast import literal_eval

from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.views import View
from rest_framework.parsers import FormParser
from rest_framework.views import APIView

from core.lib.meta import get_meta
from core.lib.nicktrace import get_nicks
from core.lib.opensearch import query_single_result
from core.lib.threshold import (
    annotate_num_chans,
    annotate_num_users,
    annotate_online,
    get_chans,
    get_users,
)


class Insights(LoginRequiredMixin, View):
    template_name = "ui/insights/insights.html"
    plan_name = "drilldown"

    def get(self, request):
        if not request.user.has_plan(self.plan_name):
            return render(request, "denied.html")
        return render(request, self.template_name)


class InsightsSearch(LoginRequiredMixin, View):
    # parser_classes = [JSONParser]
    template_name = "ui/insights/info.html"
    plan_name = "drilldown"

    def post(self, request):
        if not request.user.has_plan(self.plan_name):
            return HttpResponseForbidden()
        results, context = query_single_result(request)
        if not context:
            return HttpResponseForbidden()
        return render(request, self.template_name, context)


class InsightsChannels(LoginRequiredMixin, APIView):
    parser_classes = [FormParser]
    template_name = "ui/insights/channels.html"
    plan_name = "drilldown"

    def post(self, request):
        if not request.user.has_plan(self.plan_name):
            return HttpResponseForbidden()
        if "net" not in request.data:
            return HttpResponse("No net")
        if "nick" not in request.data:
            return HttpResponse("No nick")
        net = request.data["net"]
        nick = request.data["nick"]
        chans = get_chans(net, [nick])
        num_users = annotate_num_users(net, chans)
        if not chans:
            return HttpResponseForbidden()
        context = {"net": net, "nick": nick, "chans": chans, "num_users": num_users}
        return render(request, self.template_name, context)


class InsightsNicks(LoginRequiredMixin, APIView):
    parser_classes = [FormParser]
    template_name = "ui/insights/nicks.html"
    plan_name = "drilldown"

    def post(self, request):
        if not request.user.has_plan(self.plan_name):
            return HttpResponseForbidden()
        if "net" not in request.data:
            return HttpResponse("No net")
        if "nick" not in request.data:
            return HttpResponse("No nick")
        net = request.data["net"]
        nick = request.data["nick"]
        nicks = get_nicks(request, net, [nick])
        # Filter Guest
        nicks = [x for x in nicks if not x.startswith("Guest")]
        online = annotate_online(net, nicks)
        if not nicks:
            return HttpResponseForbidden()
        context = {"net": net, "nick": nick, "nicks": nicks, "online": online}
        return render(request, self.template_name, context)


class InsightsMeta(LoginRequiredMixin, APIView):
    parser_classes = [FormParser]
    template_name = "ui/insights/meta.html"
    plan_name = "drilldown"

    def post(self, request):
        if not request.user.has_plan(self.plan_name):
            return HttpResponseForbidden()
        if "net" not in request.data:
            return HttpResponse("No net")
        if "nicks" not in request.data:
            return HttpResponse("No nicks")
        net = request.data["net"]
        nicks = request.data["nicks"]
        nicks = literal_eval(nicks)
        meta = get_meta(request, net, nicks)
        unique_values = {}
        # Create a map of unique values for each key for each nick
        for x in meta:
            nick = x["nick"]
            if nick not in unique_values:
                unique_values[nick] = {}
            for k, v in x.items():
                if k not in unique_values[nick]:
                    unique_values[nick][k] = set()
                if k in ["ts", "time", "date", "id"]:
                    continue
                unique_values[nick][k].add(v)
        meta_dedup = {}
        for x in meta:
            nick = x["nick"]
            for k, v in x.items():
                if v in unique_values[nick][k]:
                    if k not in meta_dedup:
                        meta_dedup[k] = set()
                    meta_dedup[k].add(v)
                    unique_values[nick][k].remove(v)

        context = {"net": net, "nicks": nicks, "meta": meta_dedup}
        return render(request, self.template_name, context)


class InsightsInfoModal(LoginRequiredMixin, APIView):
    parser_classes = [FormParser]
    plan_name = "drilldown"
    template_name = "modals/drilldown.html"

    def post(self, request):
        if not request.user.has_plan(self.plan_name):
            return JsonResponse({"success": False})
        if "net" not in request.data:
            return JsonResponse({"success": False})
        if "nick" not in request.data:
            return JsonResponse({"success": False})
        if "channel" not in request.data:
            return JsonResponse({"success": False})
        net = request.data["net"]
        nick = request.data["nick"]
        channel = request.data["channel"]
        channels = get_chans(net, [nick])
        users = get_users(net, [channel])
        num_users = annotate_num_users(net, channels)
        num_chans = annotate_num_chans(net, users)
        if channels:
            inter_users = get_users(net, channels)
        else:
            inter_users = []
        if users:
            inter_chans = get_chans(net, users)
        else:
            inter_chans = []
        context = {
            "net": net,
            "nick": nick,
            "channel": channel,
            "chans": channels,
            "users": users,
            "inter_chans": inter_chans,
            "inter_users": inter_users,
            "num_users": num_users,
            "num_chans": num_chans,
        }
        return render(request, self.template_name, context)
