import calendar
import json
import re

from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.decorators import login_required
from django.db.models import Count
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse

from vulnerability_app.forms import UserForm
from vulnerability_app.models import Url, UrlType


def index(request):
    return render(request, 'vulnerability_app/index.html')


@login_required
def special(request):
    return HttpResponse("You are logged in !")


@login_required
def user_logout(request):
    logout(request)
    return HttpResponseRedirect(reverse('index'))


def register(request):
    registered = False
    if request.method == 'POST':
        user_form = UserForm(data=request.POST)
        # profile_form = UserProfileInfoForm(data=request.POST)
        # if user_form.is_valid() and profile_form.is_valid():
        if user_form.is_valid():
            user = user_form.save()
            user.set_password(user.password)
            user.save()
            # profile = profile_form.save(commit=False)
            # profile.user = user
            # profile.save()
            registered = True
        else:
            print(user_form.errors)
    else:
        user_form = UserForm()
        # profile_form = UserProfileInfoForm()
    return render(request, 'vulnerability_app/registration.html',
                  {'user_form': user_form,
                   # 'profile_form': profile_form,
                   'registered': registered})


def user_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(username=username, password=password)
        if user:
            if user.is_active:
                login(request, user)
                return HttpResponseRedirect(reverse('index'))
            else:
                return HttpResponse("Your account was inactive.")
        else:
            print("Someone tried to login and failed.")
            print("They used username: {} and password: {}".format(username, password))
            return HttpResponse("Invalid login details given")
    else:
        return render(request, 'vulnerability_app/login.html', {})


def _is_domain_valid(url: str) -> bool:
    domain_regex = "^https?:\/\/([0-9a-zA-Z.-]+)\/"
    #  Check if the url's domain matches the given regex
    try:
        re.search(domain_regex, url).group(1)
    except AttributeError:
        return False
    # Check if the url'domain contains more then 3 dot(.) characters
    if url.count(".") > 3:
        return False
    # if url_domain not in set(safe_domain.domain for safe_domain in get_safe_domains()):
    #     return False
    return True


def url_types_to_dict() -> dict:
    """
    Retrieves all the url_types from DB mapped to their IDs.
    e.g.:
    {'phishing': 1, 'spam': 2, 'defacement': 3, 'malware': 4, 'benign': 5}
    :return:
    """
    url_types_mappings = dict()
    for url_type in UrlType.objects.all():
        url_types_mappings[url_type.name] = url_type.id
    return url_types_mappings


def compute_occurrences(request):
    quarter1 = Url.objects.values('url_type').filter(accessed_on__range=["2020-01-01", "2020-03-31"]).annotate(
        count=Count("path"))
    quarter2 = Url.objects.values('url_type').filter(accessed_on__range=["2020-04-01", "2020-06-30"]).annotate(
        count=Count("path"))
    quarter3 = Url.objects.values('url_type').filter(accessed_on__range=["2020-07-01", "2020-09-30"]).annotate(
        count=Count("path"))
    quarter4 = Url.objects.values('url_type').filter(accessed_on__range=["2020-10-01", "2020-12-31"]).annotate(
        count=Count("path"))

    q1 = [item["count"] for item in quarter1]
    q2 = [item["count"] for item in quarter2]
    q3 = [item["count"] for item in quarter3]
    q4 = [item["count"] for item in quarter4]

    categories = [key.upper() for key in url_types_to_dict().keys()]

    return render(request,
                  "vulnerability_app/malicious_urls_occurrences.html",
                  {"urls_categories": json.dumps(categories),
                   "q1": q1,
                   "q2": q2,
                   "q3": q3,
                   "q4": q4,
                   }
                  )


def monthly_report(request):
    phishing_url_type_id = url_types_to_dict()["phishing"]
    result = []
    for _month in range(1, 13):
        # Take into account only the phishing URLs
        by_month = Url.objects.filter(url_type=phishing_url_type_id).filter(accessed_on__month=_month).all()
        valid = []
        invalid = []
        for url in by_month:
            if _is_domain_valid(url.path):
                valid.append(url)
            else:
                invalid.append(url)
        result.append([len(valid), len(invalid)])

    safe_urls = {"name": "Safe", "data": [item[0] for item in result]}
    malicious_urls = {"name": "Malicious", "data": [item[1] for item in result]}

    return render(request,
                  "vulnerability_app/monthly_report.html",
                  {
                      "categories": json.dumps(list(calendar.month_name[1:])),
                      "safe_urls": safe_urls,
                      "malicious_urls": malicious_urls
                  }
                  )
