"""
shared/mixins/softdelete.py
============================
Mixin de borrado suave (soft delete).
En lugar de eliminar registros de la BD, los marca como inactivos.
Esto preserva el historial y permite restauración.

Uso:
    class MiModelo(SoftDeleteModel):
        ...
    
    # Borrar (soft):
    obj.delete()     → marca deleted_at, no borra de BD
    
    # Restaurar:
    obj.restore()
    
    # Borrar definitivamente:
    obj.hard_delete()
    
    # QuerySet solo activos (default):
    MiModelo.objects.all()       → solo no borrados
    MiModelo.all_objects.all()   → todos incluyendo borrados
"""

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


class SoftDeleteQuerySet(models.QuerySet):
    """QuerySet que excluye registros borrados por defecto."""

    def delete(self):
        """Borrado suave masivo — marca todos como borrados."""
        return self.update(deleted_at=timezone.now())

    def hard_delete(self):
        """Borrado real de BD — usar con precaución."""
        return super().delete()

    def alive(self):
        """Retorna solo registros activos (no borrados)."""
        return self.filter(deleted_at__isnull=True)

    def dead(self):
        """Retorna solo registros borrados."""
        return self.filter(deleted_at__isnull=False)


class SoftDeleteManager(models.Manager):
    """Manager que usa SoftDeleteQuerySet y filtra borrados por defecto."""

    def get_queryset(self):
        return SoftDeleteQuerySet(self.model).filter(deleted_at__isnull=True)


class SoftDeleteModel(models.Model):
    """
    Modelo abstracto con borrado suave.
    Agrega deleted_at: None = activo, datetime = borrado.
    """

    deleted_at = models.DateTimeField(
        null=True, blank=True,
        verbose_name='Borrado en',
        help_text='Si tiene valor, el registro está desactivado'
    )

    # Manager por defecto: excluye borrados
    objects = SoftDeleteManager()

    # Manager para acceder a TODOS los registros (incluyendo borrados)
    all_objects = models.Manager()

    class Meta:
        abstract = True

    def delete(self, using=None, keep_parents=False):
        """Borrado suave: marca deleted_at en lugar de eliminar."""
        self.deleted_at = timezone.now()
        self.save(update_fields=['deleted_at'])

    def restore(self):
        """Restaura un registro borrado."""
        self.deleted_at = None
        self.save(update_fields=['deleted_at'])

    def hard_delete(self):
        """Eliminación física de la BD. Usar solo en casos extremos."""
        super().delete()

    @property
    def is_alive(self):
        """True si el registro está activo (no borrado)."""
        return self.deleted_at is None
