"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.21

"""
from django.test import Client

from django.contrib.auth.models import Group
from django.urls import reverse

from intervention.models import Revocation
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.tests.test_views import BaseViewTestCase


class InterventionViewTestCase(BaseViewTestCase):

    @classmethod
    def setUpTestData(cls) -> None:
        super().setUpTestData()

    def setUp(self) -> None:
        super().setUp()
        # Prepare urls
        self.index_url = reverse("intervention:index", args=())
        self.new_url = reverse("intervention:new", args=())
        self.new_id_url = reverse("intervention:new-id", args=())
        self.detail_url = reverse("intervention:detail", args=(self.intervention.id,))
        self.log_url = reverse("intervention:log", args=(self.intervention.id,))
        self.edit_url = reverse("intervention:edit", args=(self.intervention.id,))
        self.remove_url = reverse("intervention:remove", args=(self.intervention.id,))
        self.share_url = reverse("intervention:share-token", args=(self.intervention.id, self.intervention.access_token,))
        self.share_create_url = reverse("intervention:share-form", args=(self.intervention.id,))
        self.run_check_url = reverse("intervention:check", args=(self.intervention.id,))
        self.record_url = reverse("intervention:record", args=(self.intervention.id,))
        self.report_url = reverse("intervention:report", args=(self.intervention.id,))

        self.deduction.intervention = self.intervention
        self.deduction.save()
        self.deduction_new_url = reverse("intervention:new-deduction", args=(self.intervention.id,))
        self.deduction_edit_url = reverse("intervention:edit-deduction", args=(self.intervention.id, self.deduction.id,))
        self.deduction_remove_url = reverse("intervention:remove-deduction", args=(self.intervention.id, self.deduction.id))

        self.revocation = Revocation.objects.create(
            legal=self.intervention.legal
        )
        self.revocation_new_url = reverse("intervention:new-revocation", args=(self.intervention.id,))
        self.revocation_edit_url = reverse("intervention:edit-revocation", args=(self.intervention.id, self.revocation.id))
        self.revocation_remove_url = reverse("intervention:remove-revocation", args=(self.intervention.id, self.revocation.id))

    def test_views_anonymous_user(self):
        """ Check correct status code for all requests

        Assumption: User not logged in

        Returns:

        """
        # Unknown client
        client = Client()

        success_urls = [
            self.report_url,
        ]
        login_redirect_base = f"{self.login_url}?next="
        fail_urls = {
            self.detail_url: f"{login_redirect_base}{self.detail_url}",
            self.index_url: f"{login_redirect_base}{self.index_url}",
            self.log_url: f"{login_redirect_base}{self.log_url}",
            self.new_id_url: f"{login_redirect_base}{self.new_id_url}",
            self.new_url: f"{login_redirect_base}{self.new_url}",
            self.edit_url: f"{login_redirect_base}{self.edit_url}",
            self.remove_url: f"{login_redirect_base}{self.remove_url}",
            self.share_url: f"{login_redirect_base}{self.share_url}",
            self.share_create_url: f"{login_redirect_base}{self.share_create_url}",
            self.run_check_url: f"{login_redirect_base}{self.run_check_url}",
            self.record_url: f"{login_redirect_base}{self.record_url}",
            self.deduction_new_url: f"{login_redirect_base}{self.deduction_new_url}",
            self.deduction_edit_url: f"{login_redirect_base}{self.deduction_edit_url}",
            self.deduction_remove_url: f"{login_redirect_base}{self.deduction_remove_url}",
            self.revocation_new_url: f"{login_redirect_base}{self.revocation_new_url}",
            self.revocation_edit_url: f"{login_redirect_base}{self.revocation_edit_url}",
            self.revocation_remove_url: f"{login_redirect_base}{self.revocation_remove_url}",
        }

        self.assert_url_success(client, success_urls)

        for url in fail_urls:
            response = client.get(url, follow=True)
            self.assertEqual(response.redirect_chain[0], (f"{self.login_url}?next={url}", 302), msg=f"Failed for {url}. Redirect chain is {response.redirect_chain}")

    def test_views_logged_in_no_groups(self):
        """ Check correct status code for all requests

        Assumption: User logged in but has no groups

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)
        self.superuser.groups.set([])
        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
        ]
        fail_urls = [
            self.log_url,
            self.new_id_url,
            self.new_url,
            self.edit_url,
            self.remove_url,
            self.share_url,
            self.share_create_url,
            self.run_check_url,
            self.record_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)

    def test_views_logged_in_default_group_shared(self):
        """ Check correct status code for all requests

        Assumption: User logged in and is default group member

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)

        # Add user to default group
        default_group = Group.objects.get(name=DEFAULT_GROUP)
        self.superuser.groups.set([default_group])
        self.intervention.share_with_user_list([self.superuser])

        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
            self.log_url,
            self.new_id_url,
            self.new_url,
            self.edit_url,
            self.remove_url,
            self.share_create_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]
        fail_urls = [
            self.run_check_url,
            self.record_url,
        ]
        success_urls_redirect = {
            self.share_url: self.detail_url
        }

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)
        self.assert_url_success_redirect(client, success_urls_redirect)

    def test_views_logged_in_default_group_unshared(self):
        """ Check correct status code for all requests

        Assumption: User logged in and is default group member but data is not shared with

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)

        # Add user to default group
        default_group = Group.objects.get(name=DEFAULT_GROUP)
        self.superuser.groups.set([default_group])
        self.intervention.share_with_user_list([])

        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
            self.new_id_url,
            self.new_url,
        ]
        fail_urls = [
            self.run_check_url,
            self.record_url,
            self.edit_url,
            self.remove_url,
            self.share_create_url,
            self.log_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]
        success_urls_redirect = {
            self.share_url: self.detail_url
        }

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)
        self.assert_url_success_redirect(client, success_urls_redirect)

    def test_views_logged_in_zb_group_shared(self):
        """ Check correct status code for all requests

        Assumption: User logged in and is registration office member and data is shared

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)

        # Add user to zb group
        zb_group = self.groups.get(name=ZB_GROUP)
        self.superuser.groups.set([zb_group])
        self.intervention.share_with_user_list([self.superuser])

        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
            self.run_check_url,
        ]
        fail_urls = [
            self.log_url,
            self.new_id_url,
            self.new_url,
            self.edit_url,
            self.remove_url,
            self.share_create_url,
            self.record_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]
        success_urls_redirect = {
            self.share_url: self.detail_url
        }

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)
        self.assert_url_success_redirect(client, success_urls_redirect)

    def test_views_logged_in_zb_group_unshared(self):
        """ Check correct status code for all requests

        Assumption: User logged in and is registration office member but data is not shared

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)

        # Add user to zb group
        zb_group = self.groups.get(name=ZB_GROUP)
        self.superuser.groups.set([zb_group])
        self.intervention.share_with_user_list([])

        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
        ]
        fail_urls = [
            self.log_url,
            self.new_id_url,
            self.new_url,
            self.edit_url,
            self.remove_url,
            self.share_create_url,
            self.record_url,
            self.run_check_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]
        success_urls_redirect = {
            self.share_url: self.detail_url
        }

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)
        self.assert_url_success_redirect(client, success_urls_redirect)

    def test_views_logged_in_ets_group_shared(self):
        """ Check correct status code for all requests

        Assumption: User logged in and is conservation office member and data is shared with

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)

        # Add user to ets group
        ets_group = Group.objects.get(name=ETS_GROUP)
        self.superuser.groups.set([ets_group])
        self.intervention.share_with_user_list([self.superuser])

        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
            self.record_url,
        ]
        fail_urls = [
            self.log_url,
            self.new_id_url,
            self.new_url,
            self.edit_url,
            self.remove_url,
            self.share_create_url,
            self.run_check_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]
        success_urls_redirect = {
            self.share_url: self.detail_url
        }

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)
        self.assert_url_success_redirect(client, success_urls_redirect)

    def test_views_logged_in_ets_group_unshared(self):
        """ Check correct status code for all requests

        Assumption: User logged in and is registration office member and data is not shared with

        Returns:

        """
        # Login client
        client = Client()
        client.login(username=self.superuser.username, password=self.superuser_pw)

        # Add user to default group
        ets_group = Group.objects.get(name=ETS_GROUP)
        self.superuser.groups.set([ets_group])
        self.intervention.share_with_user_list([])

        success_urls = [
            self.index_url,
            self.report_url,
            self.detail_url,
        ]
        fail_urls = [
            self.record_url,
            self.log_url,
            self.new_id_url,
            self.new_url,
            self.edit_url,
            self.remove_url,
            self.share_create_url,
            self.run_check_url,
            self.revocation_new_url,
            self.revocation_edit_url,
            self.revocation_remove_url,
            self.deduction_new_url,
            self.deduction_edit_url,
            self.deduction_remove_url,
        ]
        # Define urls where a redirect to a specific location is the proper response
        success_urls_redirect = {
            self.share_url: self.detail_url
        }

        self.assert_url_success(client, success_urls)
        self.assert_url_fail(client, fail_urls)
        self.assert_url_success_redirect(client, success_urls_redirect)