"""
app_nutzer/models.py

Models for persons (app users) and tenancy contracts.
Migrated from:
  app/Models/User.php     → User
  app/Models/ReuMietV.php → ReuMietV
"""

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models

from app_real_estate.models import RealEstate, RealEstateUnit

from .constants import ANREDEN
# ---------------------------------------------------------------------------
# Custom User Manager
# ---------------------------------------------------------------------------
class UserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('E-Mail-Adresse ist erforderlich.')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(username, password, **extra_fields)


# ---------------------------------------------------------------------------
# User  (migrated from app/Models/User.php)
# Primary key: PersonenID (matches existing DB schema)
# USERNAME_FIELD: email  (login uses email)
# ---------------------------------------------------------------------------
class User(AbstractBaseUser, PermissionsMixin):
    PersonenID = models.PositiveIntegerField(primary_key=True, verbose_name="PersID")
    lastname = models.CharField(max_length=255, blank=True, null=True)
    firstname = models.CharField(max_length=255, blank=True, null=True)
    companyname = models.CharField(max_length=255, blank=True, null=True)
    email = models.EmailField(unique=True)
    VISysEMailPreference = models.IntegerField(default=0, null=True, blank=True)
    SalutationID = models.IntegerField(null=True, blank=True)
    SaAnschrift = models.CharField(max_length=255, blank=True, null=True)
    SaAnrede = models.CharField(max_length=255, blank=True, null=True)
    SaBriefkopf = models.TextField(blank=True, null=True)
    last_login = models.DateTimeField(null=True, blank=True, verbose_name="Letzte Anmeldung")
    last_login_ip = models.CharField(max_length=45, null=True, blank=True)
    email_verified_at = models.DateTimeField(null=True, blank=True)
    remember_token = models.CharField(max_length=100, blank=True, null=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True, null=True)
    updated_at = models.DateTimeField(auto_now=True, null=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    class Meta:
        db_table = 'users'
        verbose_name = 'Nutzer'
        verbose_name_plural = 'Nutzer'

    # models.py – Methoden im User Model

    def get_name(self) -> str:
        if self.SalutationID is None:
            raise ValueError('Keine Salutation/Anrede hinterlegt!')
        
        sid = self.SalutationID

        if sid in [ANREDEN.HERR_PER_SIE, ANREDEN.FRAU_PER_SIE]:
            if self.firstname:
                return f"{self.firstname} {self.lastname}"
            return self.lastname or ''

        elif sid in [ANREDEN.HERR_PER_DU, ANREDEN.FRAU_PER_DU, ANREDEN.NAT_PERSON_PER_DU]:
            return self.firstname or ''

        elif sid in [ANREDEN.FIRMA, ANREDEN.GENOSSENSCHAFT]:
            return self.companyname or ''

        elif sid == ANREDEN.WEG:
            return f"WEG {self.companyname}"

        elif sid == ANREDEN.WG_NEUTRAL:
            return f"WG {self.companyname}"

        elif sid == ANREDEN.EHELEUTE_W_M:
            if self.firstname:
                parts = self.firstname.split("|")
                vn1 = parts[0] if len(parts) > 0 else ''
                vn2 = parts[1] if len(parts) > 1 else ''
                return f"{vn1} u. {vn2} {self.lastname}"
            return f"Eheleute {self.lastname}"

        elif sid in [ANREDEN.WG_W_M, ANREDEN.WG_W_W, ANREDEN.WG_M_M]:
            if self.companyname:
                p1, p2   = self.companyname.split("|")
                vn1, nn1 = p1.split(";")
                vn2, nn2 = p2.split(";")
                return f"{vn1} {nn1} u. {vn2} {nn2}"
            return f"Datensatz fehlerhaft {self.companyname}"

        elif sid in [ANREDEN.FREIIN, ANREDEN.FREIFRAU, ANREDEN.FREIHERR]:
            return f"{self.SaAnrede} {self.lastname}"

        elif sid == ANREDEN.ERBENGEMEINSCHAFT:
            return f"Erbengemeinschaft {self.companyname}"

        else:
            raise NotImplementedError(f"Bitte Salutation {sid} implementieren")

    @property
    def fullName(self) -> str:
        return self.get_name()

    def get_name_for_briefkopf(self):
        """
        Migrated from MietVController::getNameForBriefkopf().
        Returns the salutation name for correspondence headers.
        """
        sid = self.SalutationID

        if sid in [1, 2, 3, 4]:
            name = f"{self.SaAnrede or ''} {self.lastname or ''}"
        elif sid == 10:
            name = self.companyname or ''
        elif sid == 13:
            if self.firstname:
                parts = self.firstname.split('|')
                vn1 = parts[0] if len(parts) > 0 else ''
                vn2 = parts[1] if len(parts) > 1 else ''
                name = f"Eheleute\n{vn1} u. {vn2} {self.lastname or ''}"
            else:
                name = f"Eheleute\n{self.lastname or ''}"
        elif sid in [15, 16]:
            cn = self.companyname or ''
            try:
                parts = cn.split('|')
                vn1 = parts[0].split(';')[0]
                vn2 = parts[1].split(';')[0]
                nn1 = parts[0].split(';')[1]
                nn2 = parts[1].split(';')[1]
                template = self.SaBriefkopf or ''
                name = template.replace('#NN1', nn1).replace('#NN2', nn2).replace('#VN2', vn2).replace('#VN1', vn1)
            except (IndexError, AttributeError):
                name = cn
        elif sid in [21, 22, 23]:
            name = f"{self.SaAnschrift or ''} {self.firstname or ''} {self.lastname or ''}"
        else:
            name = ''

        return f' {name}'

    def __str__(self):
        return self.email


# ---------------------------------------------------------------------------
# ReuMietV  (migrated from app/Models/ReuMietV.php)
# Tenancy / rental agreement linking unit to tenant (Person)
# ---------------------------------------------------------------------------
class ReuMietV(models.Model):
    MietVID = models.IntegerField(primary_key=True)
    REUID = models.ForeignKey(
        RealEstateUnit,
        db_column='REUID',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
    )
    MieterID = models.IntegerField(null=True, blank=True)  # FK to users.PersonenID
    ContractValidFrom = models.DateField(null=True, blank=True)
    ContractValidUntil = models.DateField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True, null=True)
    updated_at = models.DateTimeField(auto_now=True, null=True)

    class Meta:
        db_table = 'reu_miet_v_s'
        verbose_name = 'Mietverhältniss'
        verbose_name_plural = 'Mietverhältnisse'


    def __str__(self):
        return f'MietVID {self.MietVID}'


# ---------------------------------------------------------------------------
# ReuEigentuemer – Eigentumsverhaeltnis
#
# Gegenstueck zu ReuMietV. Analog zu xin, wo Mieter in tblREUTeanants und
# Eigentuemer in tblREUOwnerLinker als getrennte Tabellen liegen
# (xds_django_toolbox/django_components/models/immobilie.py).
#
# Feldabbildung xin -> Portal:
#   REUOwnerLinker.ID          -> EigentumID
#   REUOwnerLinker.REUID       -> REUID
#   REUOwnerLinker.REUOwnerID  -> EigentuemerID   (users.PersonenID)
#   REUOwnerLinker.ValidFrom   -> ValidFrom
#   REUOwnerLinker.ValidUntil  -> ValidUntil
#
# Zusammengefuehrt werden Miet- und Eigentumsverhaeltnisse NICHT hier, sondern
# ausschliesslich in core.services.nutzungsverhaeltnisse. Wer die beiden
# Tabellen anderswo per Hand vereinigt, laeuft der Fachlogik davon.
#
# Anders als reu_miet_v_s wird diese Tabelle von Django angelegt, folgt also
# dem Modell. ValidUntil darf offen bleiben -- ein Eigentumsverhaeltnis hat
# in der Regel kein Enddatum.
# ---------------------------------------------------------------------------
class ReuEigentuemer(models.Model):
    EigentumID = models.IntegerField(primary_key=True, verbose_name='Eigentums-ID')
    REUID = models.ForeignKey(
        RealEstateUnit,
        db_column='REUID',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='eigentumsverhaeltnisse',
        verbose_name='Nutzungseinheit',
    )
    EigentuemerID = models.PositiveIntegerField(null=True, blank=True)  # -> users.PersonenID (int unsigned)
    ValidFrom = models.DateField(null=True, blank=True, verbose_name='Gueltig von')
    ValidUntil = models.DateField(null=True, blank=True, verbose_name='Gueltig bis')
    created_at = models.DateTimeField(auto_now_add=True, null=True)
    updated_at = models.DateTimeField(auto_now=True, null=True)

    class Meta:
        db_table = 'reu_eigentuemer'
        verbose_name = 'Eigentumsverhaeltnis'
        verbose_name_plural = 'Eigentumsverhaeltnisse'
        indexes = [
            models.Index(fields=['REUID', 'EigentuemerID'], name='reu_eig_reu_person_idx'),
            models.Index(fields=['EigentuemerID'], name='reu_eig_person_idx'),
        ]

    def __str__(self):
        return f'EigentumID {self.EigentumID}'


# ---------------------------------------------------------------------------
# Anmelde-Log und Besuche – Grundlage der Nutzungsstatistik in xin
#
# NutzerAnmeldung  : jeder Anmeldeversuch eines Portal-Nutzers (users).
#                    Fehlversuche nur, wenn die E-Mail einem Nutzer gehoert.
# NutzerAnmeldungIP: IP getrennt vom Log. Darf jederzeit geloescht werden
#                    (manage.py anmelde_ips_loeschen), die Statistik bleibt.
# NutzerBesuch     : ein Eintrag pro Nutzer und Tag mit Aktivitaet – zaehlt
#                    auch Besuche mit noch laufender Session.
#
# Admin-Anmeldungen (AdminUser, users.is_staff/is_superuser) werden nicht
# erfasst. PersonenID bewusst ohne FK: der Log bleibt, wenn ein Nutzer
# geloescht wird.
# ---------------------------------------------------------------------------
class NutzerAnmeldung(models.Model):
    PersonenID = models.PositiveIntegerField(db_index=True)
    zeitpunkt = models.DateTimeField(auto_now_add=True, db_index=True)
    erfolgreich = models.BooleanField(default=True)

    class Meta:
        db_table = 'nutzer_anmeldung'
        verbose_name = 'Anmeldung'
        verbose_name_plural = 'Anmeldungen'

    def __str__(self):
        return f'{self.PersonenID} {self.zeitpunkt:%Y-%m-%d %H:%M}'


class NutzerAnmeldungIP(models.Model):
    anmeldung = models.OneToOneField(
        NutzerAnmeldung,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name='ip_info',
    )
    ip = models.CharField(max_length=45)
    user_agent = models.CharField(max_length=255, blank=True, default='')

    class Meta:
        db_table = 'nutzer_anmeldung_ip'
        verbose_name = 'Anmeldung-IP'
        verbose_name_plural = 'Anmeldung-IPs'


class NutzerBesuch(models.Model):
    PersonenID = models.PositiveIntegerField()
    tag = models.DateField(db_index=True)
    erster_zugriff = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'nutzer_besuch'
        verbose_name = 'Besuch'
        verbose_name_plural = 'Besuche'
        constraints = [
            models.UniqueConstraint(fields=['PersonenID', 'tag'], name='nutzer_besuch_person_tag_uniq'),
        ]
