from urllib.parse import urljoin

import requests
from django.conf import settings
from django.contrib import messages
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.http import require_GET, require_POST

from NEMO.decorators import staff_member_required
from NEMO.models import MembershipHistory, Tool, ToolQualificationGroup, User
from NEMO.views.users import get_identity_service


@staff_member_required
@require_GET
def qualifications(request):
	"""Present a web page to allow staff to qualify or disqualify users on particular tools."""
	users = User.objects.filter(is_active=True)
	tools = Tool.objects.filter(visible=True)
	tool_groups = ToolQualificationGroup.objects.all()
	return render(
		request, "qualifications.html", {"users": users, "tools": list(tools), "tool_groups": list(tool_groups)}
	)


@staff_member_required
@require_POST
def modify_qualifications(request):
	"""Change the tools that a set of users is qualified to use."""
	action = request.POST.get("action")
	if action != "qualify" and action != "disqualify":
		return HttpResponseBadRequest("You must specify that you are qualifying or disqualifying users.")
	users = request.POST.getlist("chosen_user[]") or request.POST.get("chosen_user") or []
	users = User.objects.in_bulk(users)
	if users == {}:
		return HttpResponseBadRequest("You must specify at least one user.")
	tools = request.POST.getlist("chosen_tool[]") or request.POST.getlist("chosen_tool") or []
	tool_groups = (
		request.POST.getlist("chosen_toolqualificationgroup[]")
		or request.POST.getlist("chosen_toolqualificationgroup")
		or []
	)
	# Add tools from tool group
	tools.extend(
		[
			tool.id
			for tool_group in ToolQualificationGroup.objects.filter(id__in=tool_groups)
			for tool in tool_group.tools.all()
		]
	)
	tools = Tool.objects.in_bulk(tools)
	if tools == {}:
		return HttpResponseBadRequest("You must specify at least one tool.")

	for user in users.values():
		original_qualifications = set(user.qualifications.all())
		if action == "qualify":
			user.qualifications.add(*tools)
			original_physical_access_levels = set(user.physical_access_levels.all())
			physical_access_level_automatic_enrollment = list(
				set(
					[
						t.grant_physical_access_level_upon_qualification
						for t in tools.values()
						if t.grant_physical_access_level_upon_qualification
					]
				)
			)
			user.physical_access_levels.add(*physical_access_level_automatic_enrollment)
			current_physical_access_levels = set(user.physical_access_levels.all())
			added_physical_access_levels = set(current_physical_access_levels) - set(original_physical_access_levels)
			for access_level in added_physical_access_levels:
				entry = MembershipHistory()
				entry.authorizer = request.user
				entry.parent_content_object = access_level
				entry.child_content_object = user
				entry.action = entry.Action.ADDED
				entry.save()
			if get_identity_service().get("available", False):
				for t in tools:
					tool = Tool.objects.get(id=t)
					if tool.grant_badge_reader_access_upon_qualification:
						parameters = {
							"username": user.username,
							"domain": user.domain,
							"requested_area": tool.grant_badge_reader_access_upon_qualification,
						}
						timeout = settings.IDENTITY_SERVICE.get("timeout", 3)
						requests.put(
							urljoin(settings.IDENTITY_SERVICE["url"], "/add/"), data=parameters, timeout=timeout
						)
		elif action == "disqualify":
			user.qualifications.remove(*tools)
		current_qualifications = set(user.qualifications.all())
		# Record the qualification changes for each tool:
		added_qualifications = set(current_qualifications) - set(original_qualifications)
		for tool in added_qualifications:
			entry = MembershipHistory()
			entry.authorizer = request.user
			entry.parent_content_object = tool
			entry.child_content_object = user
			entry.action = entry.Action.ADDED
			entry.save()
		removed_qualifications = set(original_qualifications) - set(current_qualifications)
		for tool in removed_qualifications:
			entry = MembershipHistory()
			entry.authorizer = request.user
			entry.parent_content_object = tool
			entry.child_content_object = user
			entry.action = entry.Action.REMOVED
			entry.save()

	if request.POST.get("redirect") == "true":
		messages.success(request, "Tool qualifications were successfully modified")
		return redirect("qualifications")
	else:
		return HttpResponse()


@staff_member_required
@require_GET
def get_qualified_users(request):
	tool = get_object_or_404(Tool, id=request.GET.get("tool_id"))
	users = User.objects.filter(is_active=True)
	dictionary = {"tool": tool, "users": users, "expanded": True}
	return render(request, "tool_control/qualified_users.html", dictionary)
