"""
Permission and Role Permission models for fine-grained access control.
"""
import enum
from sqlalchemy import Column, String, Boolean, Enum, Integer, ForeignKey, Text, UniqueConstraint
from sqlalchemy.orm import relationship

from app.models.base import BaseModel


class PermissionResource(str, enum.Enum):
    """Resources that can be protected by permissions."""
    # Users & Auth
    USERS = "users"
    # Establishments
    ESTABLISHMENTS = "establishments"
    # Rooms
    ROOMS = "rooms"
    ROOM_TYPES = "room_types"
    # Clients
    CLIENTS = "clients"
    DOCUMENTS = "documents"
    # Reservations
    RESERVATIONS = "reservations"
    CHECKIN = "checkin"
    # Finance
    FOLIOS = "folios"
    PAYMENTS = "payments"
    INVOICES = "invoices"
    # Operations
    DEPARTMENTS = "departments"
    REPORTS = "reports"
    BUDGETS = "budgets"
    # CRM
    LOYALTY = "loyalty"
    WAITLIST = "waitlist"
    NOTIFICATIONS = "notifications"


class PermissionAction(str, enum.Enum):
    """CRUD actions for permissions."""
    CREATE = "create"
    READ = "read"
    UPDATE = "update"
    DELETE = "delete"
    APPROVE = "approve"   # For workflows (budget approval, etc.)
    EXPORT = "export"     # Export to PDF/Excel
    MANAGE = "manage"     # Full admin access to resource


class RolePermission(BaseModel):
    """
    Maps a role to specific resource/action permissions.
    Allows granular per-role access control beyond simple role checks.
    """
    __tablename__ = "role_permissions"
    __table_args__ = (
        UniqueConstraint("role", "resource", "action", name="uq_role_resource_action"),
    )

    role = Column(String(50), nullable=False, index=True)
    resource = Column(Enum(PermissionResource), nullable=False, index=True)
    action = Column(Enum(PermissionAction), nullable=False)
    is_allowed = Column(Boolean, default=True, nullable=False)
    description = Column(Text, nullable=True)

    def __repr__(self) -> str:
        return f"<RolePermission {self.role}:{self.resource.value}:{self.action.value}>"


class UserPermissionOverride(BaseModel):
    """
    Per-user permission overrides (grant or deny specific permissions
    beyond what the role provides).
    """
    __tablename__ = "user_permission_overrides"
    __table_args__ = (
        UniqueConstraint("user_id", "resource", "action", name="uq_user_resource_action"),
    )

    user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
    resource = Column(Enum(PermissionResource), nullable=False)
    action = Column(Enum(PermissionAction), nullable=False)
    is_allowed = Column(Boolean, nullable=False)  # True=grant, False=deny
    reason = Column(Text, nullable=True)

    # Relationships
    user = relationship("User", foreign_keys=[user_id])

    def __repr__(self) -> str:
        status = "GRANT" if self.is_allowed else "DENY"
        return f"<UserPermissionOverride {status} user:{self.user_id} {self.resource.value}:{self.action.value}>"
