# app/modules/tenancy/models/admin_platform.py
"""
AdminPlatform junction table for many-to-many relationship between Admin Users and Platforms.

This enables platform-scoped admin access:
- Super Admins: Have role='super_admin' on User model, bypass this table
- Platform Admins: Have role='platform_admin', assigned to specific platforms via this junction table

A platform admin CAN be assigned to multiple platforms (e.g., both OMS and Loyalty).
"""

from datetime import UTC, datetime

from sqlalchemy import (
    Boolean,
    Column,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    UniqueConstraint,
)
from sqlalchemy.orm import relationship

from app.core.database import Base
from models.database.base import TimestampMixin


class AdminPlatform(Base, TimestampMixin):
    """
    Junction table linking admin users to platforms they can manage.

    Allows a platform admin to:
    - Manage specific platforms only (not all)
    - Be assigned to multiple platforms
    - Have assignment tracked for audit purposes

    Example:
    - User "john@example.com" (admin) can manage OMS platform only
    - User "jane@example.com" (admin) can manage both OMS and Loyalty platforms
    """

    __tablename__ = "admin_platforms"

    id = Column(Integer, primary_key=True, index=True)

    # ========================================================================
    # Foreign Keys
    # ========================================================================

    user_id = Column(
        Integer,
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        comment="Reference to the admin user",
    )

    platform_id = Column(
        Integer,
        ForeignKey("platforms.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        comment="Reference to the platform",
    )

    # ========================================================================
    # Assignment Status
    # ========================================================================

    is_active = Column(
        Boolean,
        default=True,
        nullable=False,
        comment="Whether the admin assignment is active",
    )

    # ========================================================================
    # Audit Fields
    # ========================================================================

    assigned_at = Column(
        DateTime(timezone=True),
        default=lambda: datetime.now(UTC),
        nullable=False,
        comment="When the admin was assigned to this platform",
    )

    assigned_by_user_id = Column(
        Integer,
        ForeignKey("users.id", ondelete="SET NULL"),
        nullable=True,
        comment="Super admin who made this assignment",
    )

    # ========================================================================
    # Relationships
    # ========================================================================

    user = relationship(
        "User",
        foreign_keys=[user_id],
        back_populates="admin_platforms",
    )

    platform = relationship(
        "Platform",
        back_populates="admin_platforms",
    )

    assigned_by = relationship(
        "User",
        foreign_keys=[assigned_by_user_id],
    )

    # ========================================================================
    # Constraints & Indexes
    # ========================================================================

    __table_args__ = (
        # Each admin can only be assigned to a platform once
        UniqueConstraint(
            "user_id",
            "platform_id",
            name="uq_admin_platform",
        ),
        # Performance indexes
        Index(
            "idx_admin_platform_active",
            "user_id",
            "platform_id",
            "is_active",
        ),
        Index(
            "idx_admin_platform_user_active",
            "user_id",
            "is_active",
        ),
    )

    # ========================================================================
    # Properties
    # ========================================================================

    @property
    def platform_code(self) -> str | None:
        """Get the platform code for this assignment."""
        return self.platform.code if self.platform else None

    @property
    def platform_name(self) -> str | None:
        """Get the platform name for this assignment."""
        return self.platform.name if self.platform else None

    def __repr__(self) -> str:
        return (
            f"<AdminPlatform("
            f"user_id={self.user_id}, "
            f"platform_id={self.platform_id}, "
            f"is_active={self.is_active})>"
        )


__all__ = ["AdminPlatform"]
