import uuid

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from .errors import AppError
from .models import MembershipRole, Permission, Role, RolePermission, WorkspaceMembership


async def permissions_for(session: AsyncSession, *, workspace_id: uuid.UUID,
                          user_id: uuid.UUID) -> set[str]:
    statement = (
        select(Permission.key)
        .join(RolePermission, RolePermission.permission_key == Permission.key)
        .join(Role, Role.id == RolePermission.role_id)
        .join(MembershipRole, MembershipRole.role_id == RolePermission.role_id)
        .join(WorkspaceMembership, WorkspaceMembership.id == MembershipRole.membership_id)
        .where(
            WorkspaceMembership.workspace_id == workspace_id,
            WorkspaceMembership.user_id == user_id,
            WorkspaceMembership.status == "active",
            MembershipRole.workspace_id == workspace_id,
            RolePermission.workspace_id == workspace_id,
            Role.workspace_id == workspace_id,
        )
    )
    return set((await session.scalars(statement)).all())


async def authorize(session: AsyncSession, *, workspace_id: uuid.UUID, user_id: uuid.UUID,
                    permission: str) -> None:
    if permission not in await permissions_for(
        session, workspace_id=workspace_id, user_id=user_id
    ):
        raise AppError("PERMISSION_DENIED", "You do not have permission for this action.", 403)
