"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 30.08.23

"""
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse

from compensation.models import EcoAccountDocument
from konova.tests.test_views import BaseTestCase
from konova.utils.message_templates import DOCUMENT_REMOVED_TEMPLATE, DEDUCTION_REMOVED
from user.models import UserAction


class EcoAccountTestCase(BaseTestCase):

    def setUp(self) -> None:
        super().setUp()

    def test_str(self):
        self.assertEqual(str(self.eco_account), f"{self.eco_account.identifier} ({self.eco_account.title})")

    def test_save(self):
        old_id = self.eco_account.identifier
        self.assertIsNotNone(self.eco_account.identifier)
        self.eco_account.identifier = None
        self.eco_account.save()
        self.assertIsNotNone(self.eco_account.identifier)
        self.assertNotEqual(old_id, self.eco_account.identifier)

    def test_property_deductions_surface_sum(self):
        self.assertEqual(
            self.eco_account.deductions_surface_sum,
            self.eco_account.get_deductions_surface()
        )

    def test_get_documents(self):
        docs = self.eco_account.get_documents()
        self.assertEqual(docs.count(), 0)
        doc = self.create_dummy_document(EcoAccountDocument, self.eco_account)
        self.assertIn(doc, self.eco_account.get_documents())

    def test_get_share_link(self):
        self.assertEqual(
            self.eco_account.get_share_link(),
            reverse(
                "compensation:acc:share-token",
                args=(self.eco_account.id, self.eco_account.access_token)
            )
        )

    def test_get_deductable_rest_relative(self):
        self.assertEqual(self.eco_account.deductions.count(), 0)
        self.eco_account.deductable_surface = 5.0
        self.eco_account.save()
        self.eco_account.update_deductable_rest()

        self.assertEqual(self.eco_account.get_deductable_rest_relative(), 100)
        self.eco_account.deductable_surface = None
        self.eco_account.save()
        self.assertEqual(self.eco_account.get_deductable_rest_relative(), 0)


class EcoAccountDocumentTestCase(BaseTestCase):
    def setUp(self) -> None:
        super().setUp()

    def test_delete(self):
        doc = self.create_dummy_document(
            EcoAccountDocument,
            self.eco_account
        )
        doc_title = doc.title
        docs = self.eco_account.get_documents()
        self.assertIn(doc, docs)

        doc.delete(user=self.superuser)
        last_log = self.eco_account.log.first()
        self.assertEqual(last_log.user, self.superuser)
        self.assertEqual(last_log.action, UserAction.EDITED)
        self.assertEqual(last_log.comment, DOCUMENT_REMOVED_TEMPLATE.format(
            doc_title
        ))
        try:
            doc.refresh_from_db()
            self.fail("Document should not have been fetchable")
        except ObjectDoesNotExist:
            pass


class EcoAccountDeductionTestCase(BaseTestCase):
    def setUp(self) -> None:
        super().setUp()

    def test_str(self):
        self.assertEqual(str(self.deduction), f"{self.deduction.surface} of {self.deduction.account}")

    def test_delete(self):
        self.deduction.account = self.eco_account
        self.deduction.intervention = self.intervention
        self.deduction.save()

        self.eco_account.update_deductable_rest()
        old_deductable_rest = self.eco_account.deductable_rest
        deduction_surface = self.deduction.surface

        self.deduction.delete(self.superuser)

        last_log_intervention = self.intervention.log.first()
        last_log_account = self.eco_account.log.first()
        logs = [
            last_log_intervention,
            last_log_account,
        ]
        for log in logs:
            self.assertEqual(log.action, UserAction.EDITED)
            self.assertEqual(log.user, self.superuser)
            self.assertEqual(log.comment, DEDUCTION_REMOVED)

        self.assertLess(old_deductable_rest, self.eco_account.deductable_rest)
        self.assertEqual(old_deductable_rest + deduction_surface, self.eco_account.deductable_rest)
        try:
            self.deduction.refresh_from_db()
            self.fail("Deduction still fetchable after deleting")
        except ObjectDoesNotExist:
            pass