"""
Tests für core.mixins.get_accessible_reuids
"""
from datetime import timedelta

from django.test import TestCase
from django.utils import timezone

from app_nutzer.models import ReuMietV, User
from app_real_estate.models import RealEstate, RealEstateUnit
from app_admin.mixins import get_accessible_reuids
from app_admin.models import AdminUser


# ---------------------------------------------------------------------------
# Hilfsfunktion
# ---------------------------------------------------------------------------

def _make_re():
    """Erstellt eine RealEstate-Instanz, falls noch nicht vorhanden."""
    return RealEstate.objects.get_or_create(
        REID=1,
        defaults={'Street': 'Musterstraße', 'HouseNumber': '1', 'City': 'Trier'},
    )[0]


# ---------------------------------------------------------------------------
# Tests: normaler User
# ---------------------------------------------------------------------------

class GetAccessibleReuidsNormalUserTest(TestCase):
    def setUp(self):
        re = _make_re()
        self.reu1 = RealEstateUnit.objects.create(REUID=101, REID=re, REUDesc='EG links')
        self.reu2 = RealEstateUnit.objects.create(REUID=102, REID=re, REUDesc='EG rechts')
        self.reu3 = RealEstateUnit.objects.create(REUID=103, REID=re, REUDesc='OG')

        self.user = User.objects.create(PersonenID=1, email='mieter@test.de')
        self.user.set_unusable_password()
        self.user.save()

        today = timezone.now().date()

        # Aktiver Vertrag ohne Enddatum → Zugriff ✓
        ReuMietV.objects.create(
            MietVID=1, REUID=self.reu1, MieterID=1,
            ContractValidFrom=today - timedelta(days=30),
            ContractValidUntil=None,
        )
        # Aktiver Vertrag mit zukünftigem Enddatum → Zugriff ✓
        ReuMietV.objects.create(
            MietVID=2, REUID=self.reu2, MieterID=1,
            ContractValidFrom=today - timedelta(days=10),
            ContractValidUntil=today + timedelta(days=30),
        )
        # Abgelaufener Vertrag → kein Zugriff ✗
        ReuMietV.objects.create(
            MietVID=3, REUID=self.reu3, MieterID=1,
            ContractValidFrom=today - timedelta(days=365),
            ContractValidUntil=today - timedelta(days=1),
        )

    def test_gibt_nur_aktive_vertraege_zurueck(self):
        result = get_accessible_reuids(self.user)
        self.assertIn(101, result)
        self.assertIn(102, result)
        self.assertNotIn(103, result)

    def test_gibt_keine_reuids_ohne_vertrag_zurueck(self):
        other = User.objects.create(PersonenID=2, email='kein_vertrag@test.de')
        other.set_unusable_password()
        other.save()
        result = get_accessible_reuids(other)
        self.assertEqual(result, [])

    def test_schliesst_andere_user_aus(self):
        """Verträge eines anderen Mieters dürfen nicht zurückgegeben werden."""
        other = User.objects.create(PersonenID=3, email='anderer@test.de')
        other.set_unusable_password()
        other.save()
        today = timezone.now().date()
        ReuMietV.objects.create(
            MietVID=10, REUID=self.reu3, MieterID=3,
            ContractValidFrom=today - timedelta(days=10),
            ContractValidUntil=None,
        )
        result_user = get_accessible_reuids(self.user)
        result_other = get_accessible_reuids(other)
        self.assertNotIn(103, result_user)
        self.assertIn(103, result_other)

    def test_kein_n_plus_1_query(self):
        """Konstante Anzahl Abfragen: je eine für Miet- und Eigentumstabelle."""
        with self.assertNumQueries(2):
            get_accessible_reuids(self.user)


# ---------------------------------------------------------------------------
# Tests: AdminUser
# ---------------------------------------------------------------------------

class GetAccessibleReuidsAdminUserTest(TestCase):
    def setUp(self):
        re = _make_re()
        self.reu1 = RealEstateUnit.objects.create(REUID=101, REID=re, REUDesc='EG links')
        self.reu2 = RealEstateUnit.objects.create(REUID=102, REID=re, REUDesc='EG rechts')

        self.admin = AdminUser(email='admin@test.de', username='admin')
        self.admin.set_unusable_password()
        self.admin.save()

    def test_admin_erhaelt_alle_reuids(self):
        result = get_accessible_reuids(self.admin)
        self.assertIn(101, result)
        self.assertIn(102, result)
        self.assertEqual(len(result), 2)

    def test_admin_erhaelt_reuids_auch_ohne_mietvertrag(self):
        """AdminUser bekommt REUIDs zurück, die keinen aktiven Vertrag haben."""
        result = get_accessible_reuids(self.admin)
        # reu1/reu2 existieren ohne Mietvertrag – AdminUser soll sie trotzdem sehen
        self.assertEqual(set(result), {101, 102})

    def test_kein_n_plus_1_query(self):
        with self.assertNumQueries(1):
            get_accessible_reuids(self.admin)
