"""Django models for ECP Auth.

Defines the ``UserCertificate`` model that maps X.509 digital
certificates to Django user accounts.
"""

from __future__ import annotations

import logging

from django.conf import settings
from django.db import models
from django.utils import timezone

logger: logging.Logger = logging.getLogger(__name__)


class UserCertificate(models.Model):
    """Maps an X.509 certificate to a Django user account.

    Stores certificate metadata and the PEM-encoded certificate data
    for later verification during authentication.

    Attributes:
        user: Foreign key to the Django User model.
        fingerprint_sha256: SHA-256 fingerprint of the DER-encoded certificate.
        subject_dn: The certificate subject distinguished name.
        issuer_dn: The certificate issuer distinguished name.
        serial_number: Certificate serial number (hex).
        common_name: Subject common name (CN).
        organization: Subject organization (O).
        not_valid_before: Start of the certificate validity period.
        not_valid_after: End of the certificate validity period.
        certificate_pem: PEM-encoded certificate data.
        is_active: Whether this certificate is active for authentication.
        created_at: Timestamp when the certificate record was created.
        updated_at: Timestamp of the last update.
    """

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="ecp_certificates",
        verbose_name="User",
        help_text="The user this certificate belongs to.",
    )

    fingerprint_sha256 = models.CharField(
        max_length=64,
        unique=True,
        db_index=True,
        verbose_name="SHA-256 Fingerprint",
        help_text="SHA-256 fingerprint of the DER-encoded certificate.",
    )

    subject_dn = models.CharField(
        max_length=1024,
        verbose_name="Subject DN",
        help_text="Certificate subject distinguished name (RFC 4514 format).",
    )

    issuer_dn = models.CharField(
        max_length=1024,
        verbose_name="Issuer DN",
        help_text="Certificate issuer distinguished name (RFC 4514 format).",
    )

    serial_number = models.CharField(
        max_length=256,
        verbose_name="Serial Number",
        help_text="Certificate serial number in hexadecimal.",
    )

    common_name = models.CharField(
        max_length=256,
        blank=True,
        default="",
        verbose_name="Common Name",
        help_text="Subject common name (CN).",
    )

    organization = models.CharField(
        max_length=256,
        blank=True,
        default="",
        verbose_name="Organization",
        help_text="Subject organization (O).",
    )

    not_valid_before = models.DateTimeField(
        verbose_name="Not Valid Before",
        help_text="Certificate validity start date.",
    )

    not_valid_after = models.DateTimeField(
        verbose_name="Not Valid After",
        help_text="Certificate validity end date.",
    )

    certificate_pem = models.TextField(
        verbose_name="Certificate PEM",
        help_text="PEM-encoded X.509 certificate data.",
    )

    is_active = models.BooleanField(
        default=True,
        db_index=True,
        verbose_name="Is Active",
        help_text="Whether this certificate is active for authentication.",
    )

    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name="Created At",
    )

    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name="Updated At",
    )

    class Meta:
        """Model metadata."""

        verbose_name = "User Certificate"
        verbose_name_plural = "User Certificates"
        ordering = ["-created_at"]
        indexes = [
            models.Index(
                fields=["user", "is_active"],
                name="idx_user_active_cert",
            ),
        ]

    def __str__(self) -> str:
        """Return a human-readable representation of the certificate.

        Returns:
            String with username and certificate common name.
        """
        return f"{self.user.username} — {self.common_name or self.subject_dn}"

    @property
    def is_expired(self) -> bool:
        """Check if the certificate has expired.

        Returns:
            True if the certificate is expired.
        """
        return timezone.now() > self.not_valid_after

    @property
    def is_not_yet_valid(self) -> bool:
        """Check if the certificate is not yet valid.

        Returns:
            True if the certificate is not yet valid.
        """
        return timezone.now() < self.not_valid_before
