"""
RBAC 角色相關 Models
- UserRole: 租戶層級角色 (不綁定部門)
- RoleRight: 角色對系統功能的 CRUD 權限
- UserRoleAssignment: 使用者角色分配 (直接對人，跨部門有效)
"""
from datetime import datetime
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import relationship

from app.db.base import Base


class UserRole(Base):
    """角色表 (租戶層級，不綁定部門)"""

    __tablename__ = "tenant_user_roles"
    __table_args__ = (
        UniqueConstraint("tenant_id", "seq_no", name="uq_tenant_role_seq"),
        UniqueConstraint("tenant_id", "role_code", name="uq_tenant_role_code"),
        Index("idx_roles_tenant", "tenant_id"),
    )

    id = Column(Integer, primary_key=True, index=True)
    tenant_id = Column(Integer, ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False,
                       comment="租戶 ID")
    seq_no = Column(Integer, nullable=False, comment="租戶內序號 (觸發器自動生成)")
    role_code = Column(String(100), nullable=False, comment="角色代碼 (租戶內唯一，例如 HR_ADMIN)")
    role_name = Column(String(200), nullable=False, comment="角色名稱")
    description = Column(Text, nullable=True, comment="角色說明")

    # 通用欄位
    is_active = Column(Boolean, default=True, nullable=False, comment="是否啟用")
    edit_by = Column(String(100), nullable=True, comment="最後編輯者")
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="建立時間")
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False, comment="更新時間")

    # 關聯
    tenant = relationship("Tenant", back_populates="user_roles")
    rights = relationship("RoleRight", back_populates="role", cascade="all, delete-orphan", lazy="selectin")
    user_assignments = relationship("UserRoleAssignment", back_populates="role", cascade="all, delete-orphan",
                                    lazy="dynamic")

    def __repr__(self):
        return f"<UserRole {self.role_code} - {self.role_name}>"


class RoleRight(Base):
    """角色功能權限表 (Role and System Right)"""

    __tablename__ = "tenant_role_rights"
    __table_args__ = (
        UniqueConstraint("role_id", "function_id", name="uq_role_function"),
        Index("idx_role_rights_role", "role_id"),
        Index("idx_role_rights_function", "function_id"),
    )

    id = Column(Integer, primary_key=True, index=True)
    role_id = Column(Integer, ForeignKey("tenant_user_roles.id", ondelete="CASCADE"), nullable=False,
                     comment="角色 ID")
    function_id = Column(Integer, ForeignKey("system_functions_cache.id", ondelete="CASCADE"), nullable=False,
                         comment="系統功能 ID")
    can_read = Column(Boolean, default=False, nullable=False, comment="查詢權限")
    can_create = Column(Boolean, default=False, nullable=False, comment="新增權限")
    can_update = Column(Boolean, default=False, nullable=False, comment="修改權限")
    can_delete = Column(Boolean, default=False, nullable=False, comment="刪除權限")

    # 通用欄位
    is_active = Column(Boolean, default=True, nullable=False, comment="是否啟用")
    edit_by = Column(String(100), nullable=True, comment="最後編輯者")
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="建立時間")
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False, comment="更新時間")

    # 關聯
    role = relationship("UserRole", back_populates="rights")
    function = relationship("SystemFunctionCache")

    def __repr__(self):
        perms = []
        if self.can_read: perms.append("R")
        if self.can_create: perms.append("C")
        if self.can_update: perms.append("U")
        if self.can_delete: perms.append("D")
        return f"<RoleRight role={self.role_id} fn={self.function_id} [{','.join(perms)}]>"


class UserRoleAssignment(Base):
    """使用者角色分配表 (直接對人，跨部門有效)"""

    __tablename__ = "tenant_user_role_assignments"
    __table_args__ = (
        UniqueConstraint("keycloak_user_id", "role_id", name="uq_user_role"),
        Index("idx_user_roles_tenant", "tenant_id"),
        Index("idx_user_roles_keycloak", "keycloak_user_id"),
    )

    id = Column(Integer, primary_key=True, index=True)
    tenant_id = Column(Integer, ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False,
                       comment="租戶 ID")
    keycloak_user_id = Column(String(36), nullable=False, comment="Keycloak User UUID (永久識別碼)")
    role_id = Column(Integer, ForeignKey("tenant_user_roles.id", ondelete="CASCADE"), nullable=False,
                     comment="角色 ID")

    # 審計欄位（完整記錄）
    assigned_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="分配時間")
    assigned_by = Column(String(36), nullable=True, comment="分配者 keycloak_user_id")
    revoked_at = Column(DateTime, nullable=True, comment="撤銷時間（軟刪除）")
    revoked_by = Column(String(36), nullable=True, comment="撤銷者 keycloak_user_id")

    # 通用欄位
    is_active = Column(Boolean, default=True, nullable=False, comment="是否啟用")
    edit_by = Column(String(36), nullable=True, comment="最後編輯者 keycloak_user_id")
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="建立時間")
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False, comment="更新時間")

    # 關聯
    role = relationship("UserRole", back_populates="user_assignments")

    def __repr__(self):
        return f"<UserRoleAssignment user={self.keycloak_user_id} role={self.role_id}>"
