"""Base SQLAlchemy declarative base for all database models.

This module provides the base class that all ORM models inherit from,
along with common functionality and mixins.
"""
from datetime import datetime, timezone
from typing import Any

from sqlalchemy import DateTime, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class Base(DeclarativeBase):
    """Base class for all SQLAlchemy ORM models.
    
    Provides common functionality and type annotations for all models.
    All models should inherit from this class.
    """
    pass


class TimestampMixin:
    """Mixin to add created_at and updated_at timestamp columns.
    
    Automatically tracks when records are created and updated.
    Use this mixin for models that need audit timestamps.
    
    Attributes:
        created_at: Timestamp when record was created
        updated_at: Timestamp when record was last updated
    """
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        nullable=False,
        doc="Timestamp when record was created"
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now(),
        nullable=False,
        doc="Timestamp when record was last updated"
    )


class SoftDeleteMixin:
    """Mixin to add soft delete functionality.
    
    Instead of deleting records, marks them as deleted with a timestamp.
    Useful for maintaining audit trails and allowing recovery.
    
    Attributes:
        deleted_at: Timestamp when record was soft deleted, None if active
    """
    deleted_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True),
        nullable=True,
        default=None,
        doc="Timestamp when record was soft deleted"
    )
    
    @property
    def is_deleted(self) -> bool:
        """Check if record is soft deleted."""
        return self.deleted_at is not None
    
    def soft_delete(self) -> None:
        """Mark record as deleted without removing from database."""
        self.deleted_at = datetime.now(timezone.utc)
    
    def restore(self) -> None:
        """Restore a soft deleted record."""
        self.deleted_at = None
