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

from app.models.user import User

DEFAULT_PAGE_SIZE = 20
MAX_PAGE_SIZE = 200


class AgentUserError(Exception):
    def __init__(self, message: str) -> None:
        self.message = message
        super().__init__(message)


def _list_users_filters(
    *,
    agent_id: int,
    username: str | None = None,
    role_id: int | None = None,
) -> list:
    conditions = [User.agent_id == agent_id]
    if username and username.strip():
        conditions.append(User.username.ilike(f"%{username.strip()}%"))
    if role_id is not None:
        conditions.append(User.role_id == role_id)
    return conditions


async def list_users(
    db: AsyncSession,
    *,
    agent_id: int,
    page: int = 1,
    page_size: int = DEFAULT_PAGE_SIZE,
    username: str | None = None,
    role_id: int | None = None,
) -> tuple[list[User], int]:
    page_size = min(max(page_size, 1), MAX_PAGE_SIZE)
    page = max(page, 1)
    offset = (page - 1) * page_size
    conditions = _list_users_filters(
        agent_id=agent_id,
        username=username,
        role_id=role_id,
    )

    count_stmt = select(func.count()).select_from(User)
    list_stmt = select(User).order_by(User.id.desc())
    if conditions:
        count_stmt = count_stmt.where(*conditions)
        list_stmt = list_stmt.where(*conditions)

    total = await db.scalar(count_stmt) or 0
    result = await db.scalars(list_stmt.offset(offset).limit(page_size))
    return list(result.all()), total
