"""Role-Based Access Control models: roles, permissions, role_permissions."""

import uuid
from datetime import datetime

from sqlalchemy import Boolean, Column, DateTime, ForeignKey, String, UniqueConstraint
from sqlalchemy.orm import relationship

from app.database import Base


class Role(Base):
    """A named role (admin, owner, editor, reviewer, viewer)."""

    __tablename__ = "roles"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    name = Column(String(50), unique=True, nullable=False)
    description = Column(String(500), nullable=True)
    is_system = Column(Boolean, default=False, nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)

    # relationships
    role_permissions = relationship(
        "RolePermission",
        back_populates="role",
        lazy="selectin",
        cascade="all, delete-orphan",
    )

    def __repr__(self):
        return f"<Role(id={self.id!r}, name={self.name!r})>"


class Permission(Base):
    """A granular permission identified by a unique code."""

    __tablename__ = "permissions"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    code = Column(String(100), unique=True, nullable=False)
    description = Column(String(500), nullable=True)
    resource = Column(String(50), nullable=False)
    action = Column(String(50), nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)

    # relationships
    role_permissions = relationship(
        "RolePermission",
        back_populates="permission",
        lazy="selectin",
        cascade="all, delete-orphan",
    )

    def __repr__(self):
        return f"<Permission(id={self.id!r}, code={self.code!r})>"


class RolePermission(Base):
    """Many-to-many join table between roles and permissions."""

    __tablename__ = "role_permissions"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    role_id = Column(
        String(36),
        ForeignKey("roles.id", ondelete="CASCADE"),
        nullable=False,
    )
    permission_id = Column(
        String(36),
        ForeignKey("permissions.id", ondelete="CASCADE"),
        nullable=False,
    )

    __table_args__ = (
        UniqueConstraint("role_id", "permission_id", name="uq_role_permission"),
    )

    # relationships
    role = relationship("Role", back_populates="role_permissions", lazy="selectin")
    permission = relationship(
        "Permission", back_populates="role_permissions", lazy="selectin"
    )

    def __repr__(self):
        return (
            f"<RolePermission(role_id={self.role_id!r}, "
            f"perm_id={self.permission_id!r})>"
        )
