from __future__ import annotations

from sqlalchemy import or_, select
from sqlalchemy.orm import Session

from app.modules.core.iam.scope import UserScope, get_manageable_roles
from app.modules.core.rbac.models import Permission, Role, RolePermission
from app.modules.core.iam.services import paginate_list


def search_roles(db: Session, scope: UserScope, q: str | None = None) -> list[Role]:
    roles = db.execute(select(Role).order_by(Role.name)).scalars().all() if scope.is_system_admin else get_manageable_roles(db, scope)
    query = (q or '').strip().lower()
    if not query:
        return roles
    return [r for r in roles if query in (r.name or '').lower()]


def permissions_by_role(db: Session, roles: list[Role]) -> dict[int, list[str]]:
    return {
        role.id: [code for (code,) in db.execute(
            select(Permission.code)
            .join(RolePermission, RolePermission.permission_id == Permission.id)
            .where(RolePermission.role_id == role.id)
            .order_by(Permission.code)
        ).all()]
        for role in roles
    }


def build_roles_payload(db: Session, scope: UserScope, q: str | None = None, page: int = 1, per_page: int = 10) -> dict:
    roles = search_roles(db, scope, q=q)
    paged = paginate_list(roles, page=page, per_page=per_page)
    return {
        'roles': paged.items,
        'roles_page': paged,
        'permissions_by_role': permissions_by_role(db, paged.items),
        'filters': {'q': (q or '').strip(), 'per_page': paged.per_page},
    }


def search_permissions(db: Session, q: str | None = None) -> list[Permission]:
    permissions = db.execute(select(Permission).order_by(Permission.code)).scalars().all()
    query = (q or '').strip().lower()
    if not query:
        return permissions
    return [p for p in permissions if query in (p.code or '').lower() or query in (p.name or '').lower()]


def build_permissions_payload(db: Session, q: str | None = None, page: int = 1, per_page: int = 15) -> dict:
    permissions = search_permissions(db, q=q)
    paged = paginate_list(permissions, page=page, per_page=per_page)
    return {'permissions': paged.items, 'permissions_page': paged, 'filters': {'q': (q or '').strip(), 'per_page': paged.per_page}}
