"""Anmelde-Log und Besuche – Erfassung fuer die Nutzungsstatistik in xin.

Erfasst werden nur Portal-Nutzer (``users``). Admins zaehlen nicht:
``AdminUser`` sowie Nutzer mit ``is_staff``/``is_superuser``.

Ein Fehler beim Protokollieren darf die Anmeldung nie verhindern – daher
werden Ausnahmen geloggt und verschluckt.
"""
from __future__ import annotations

import logging

from django.db import IntegrityError
from django.utils import timezone

from app_nutzer.models import NutzerAnmeldung, NutzerAnmeldungIP, NutzerBesuch, User

logger = logging.getLogger(__name__)

SESSION_KEY_BESUCH = 'nutzer_besuch_tag'


def ist_portal_nutzer(user) -> bool:
    """True fuer echte Portal-Nutzer, False fuer Admins und Anonyme."""
    return (
        isinstance(user, User)
        and user.is_authenticated
        and not user.is_staff
        and not user.is_superuser
    )


def protokolliere_anmeldung(request, user, erfolgreich: bool = True) -> None:
    if not ist_portal_nutzer(user):
        return
    try:
        anmeldung = NutzerAnmeldung.objects.create(PersonenID=user.PersonenID, erfolgreich=erfolgreich)
        NutzerAnmeldungIP.objects.create(
            anmeldung=anmeldung,
            ip=request.META.get('REMOTE_ADDR', '') or '',
            user_agent=(request.META.get('HTTP_USER_AGENT', '') or '')[:255],
        )
        if erfolgreich:
            vermerke_besuch(request, user)
    except Exception:
        logger.exception('Anmeldung von PersonenID %s nicht protokolliert', user.PersonenID)


def vermerke_besuch(request, user=None) -> None:
    """Hoechstens ein Eintrag pro Nutzer und Tag; die Session merkt sich den
    Tag, damit nicht jeder Request die DB fragt."""
    user = user or request.user
    if not ist_portal_nutzer(user):
        return
    heute = timezone.localdate()
    if request.session.get(SESSION_KEY_BESUCH) == heute.isoformat():
        return
    try:
        NutzerBesuch.objects.get_or_create(PersonenID=user.PersonenID, tag=heute)
    except IntegrityError:
        pass  # paralleler Request hat den Tag schon angelegt
    except Exception:
        logger.exception('Besuch von PersonenID %s nicht vermerkt', user.PersonenID)
        return
    request.session[SESSION_KEY_BESUCH] = heute.isoformat()
