"""RBAC configurable : rôles, permissions et exceptions utilisateur."""
from datetime import datetime, timezone
from ...extensions import db

def utcnow():
    return datetime.now(timezone.utc)

class Role(db.Model):
    __tablename__ = "roles"
    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String(80), nullable=False, unique=True)
    name = db.Column(db.String(120), nullable=False)
    description = db.Column(db.Text)
    is_system = db.Column(db.Boolean, nullable=False, default=False)
    is_active = db.Column(db.Boolean, nullable=False, default=True)
    created_at = db.Column(db.DateTime, nullable=False, default=utcnow)
    updated_at = db.Column(db.DateTime, nullable=False, default=utcnow, onupdate=utcnow)
    user_links = db.relationship("UserRole", back_populates="role", cascade="all, delete-orphan")
    permission_links = db.relationship("RolePermission", back_populates="role", cascade="all, delete-orphan")

class Permission(db.Model):
    __tablename__ = "permissions"
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.String(120), nullable=False, unique=True)
    name = db.Column(db.String(160), nullable=False)
    module = db.Column(db.String(80), nullable=False, index=True)
    action = db.Column(db.String(40), nullable=False)
    description = db.Column(db.Text)
    is_active = db.Column(db.Boolean, nullable=False, default=True)
    role_links = db.relationship("RolePermission", back_populates="permission", cascade="all, delete-orphan")
    user_links = db.relationship("UserPermission", back_populates="permission", cascade="all, delete-orphan")

class UserRole(db.Model):
    __tablename__ = "user_roles"
    __table_args__ = (db.UniqueConstraint("user_id", "role_id", name="uq_user_role"),)
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey("roles.id", ondelete="CASCADE"), nullable=False, index=True)
    assigned_at = db.Column(db.DateTime, nullable=False, default=utcnow)
    assigned_by_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="SET NULL"))
    user = db.relationship("User", foreign_keys=[user_id], back_populates="role_links")
    role = db.relationship("Role", back_populates="user_links")
    assigned_by = db.relationship("User", foreign_keys=[assigned_by_id])

class RolePermission(db.Model):
    __tablename__ = "role_permissions"
    __table_args__ = (db.UniqueConstraint("role_id", "permission_id", name="uq_role_permission"),)
    id = db.Column(db.Integer, primary_key=True)
    role_id = db.Column(db.Integer, db.ForeignKey("roles.id", ondelete="CASCADE"), nullable=False, index=True)
    permission_id = db.Column(db.Integer, db.ForeignKey("permissions.id", ondelete="CASCADE"), nullable=False, index=True)
    effect = db.Column(db.String(10), nullable=False, default="allow")
    role = db.relationship("Role", back_populates="permission_links")
    permission = db.relationship("Permission", back_populates="role_links")

class UserPermission(db.Model):
    __tablename__ = "user_permissions"
    __table_args__ = (db.UniqueConstraint("user_id", "permission_id", name="uq_user_permission"),)
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
    permission_id = db.Column(db.Integer, db.ForeignKey("permissions.id", ondelete="CASCADE"), nullable=False, index=True)
    effect = db.Column(db.String(10), nullable=False, default="allow")
    expires_at = db.Column(db.DateTime)
    note = db.Column(db.String(255))
    user = db.relationship("User", back_populates="permission_links")
    permission = db.relationship("Permission", back_populates="user_links")

