import uuid

from sqlalchemy.orm import Session

from app.core.exceptions import AppException
from app.models.role import Role
from app.models.user_role import UserRole
from common_logging import get_logger, log_execution

logger = get_logger(__name__)


class RoleService:

    @staticmethod
    @log_execution
    def create_custom_role(
        db: Session, name: str, description: str | None, tenant_id: int, created_by: int
    ) -> Role:
        code = f"tenant_{tenant_id}_role_{uuid.uuid4().hex[:8]}"
        role = Role(
            code=code,
            name=name,
            description=description,
            is_system=False,
            tenant_id=tenant_id,
            created_by=created_by,
        )
        db.add(role)
        db.commit()
        db.refresh(role)
        return role

    @staticmethod
    @log_execution
    def update_role(
        db: Session,
        role_id: int,
        name: str | None = None,
        description: str | None = None,
        updated_by: int | None = None,
    ) -> Role:
        role = db.query(Role).filter(Role.id == role_id).first()
        if not role:
            raise AppException("角色不存在", "Role not found")
        if role.is_system:
            raise AppException("系统角色不可修改", "System roles cannot be modified")
        if name:
            role.name = name
        if description is not None:
            role.description = description
        if updated_by:
            role.updated_by = updated_by
        db.commit()
        db.refresh(role)
        return role

    @staticmethod
    @log_execution
    def delete_role(db: Session, role_id: int, tenant_id: int) -> bool:
        role = db.query(Role).filter(Role.id == role_id).first()
        if not role:
            raise AppException("角色不存在", "Role not found")
        if role.is_system:
            raise AppException("系统角色不可删除", "System roles cannot be deleted")
        user_count = (
            db.query(UserRole)
            .filter(UserRole.role_id == role_id, not UserRole.is_deleted)
            .count()
        )
        if user_count > 0:
            raise AppException(
                f"角色正在被 {user_count} 个用户使用，无法删除",
                f"Role is assigned to {user_count} users and cannot be deleted",
            )
        from app.models.role_permission import RolePermission

        perm_count = (
            db.query(RolePermission)
            .filter(RolePermission.role_id == role_id, not RolePermission.is_deleted)
            .count()
        )
        if perm_count > 0:
            db.query(RolePermission).filter(RolePermission.role_id == role_id).delete()
        from app.models.role_menu import RoleMenu

        menu_count = (
            db.query(RoleMenu)
            .filter(RoleMenu.role_id == role_id, not RoleMenu.is_deleted)
            .count()
        )
        if menu_count > 0:
            db.query(RoleMenu).filter(RoleMenu.role_id == role_id).delete()
        from app.core.permissions import get_enforcer

        enforcer = get_enforcer()
        enforcer.remove_filtered_policy(0, f"role:{role.code}", str(tenant_id))
        enforcer.remove_filtered_grouping_policy(1, f"role:{role.code}", str(tenant_id))
        db.delete(role)
        db.commit()
        return True

    @staticmethod
    def list_tenant_roles(db: Session, tenant_id: int) -> list[Role]:
        roles = (
            db.query(Role)
            .filter((Role.is_system) | (Role.tenant_id == tenant_id))
            .filter(not Role.is_deleted)
            .all()
        )
        return roles

    @staticmethod
    def get_role_by_id(db: Session, role_id: int) -> Role | None:
        return db.query(Role).filter(Role.id == role_id, not Role.is_deleted).first()
