"""Shared query builder behind the "user" field type (Master datasource
fields and Form fields that pick a real system account instead of linking to
another Master's records) — used by both GET /users/picker (routers/users.py)
and field-value validation (crud/validation.py's _check_user), so a submitted
value and the options a picker actually offered can never disagree.
"""

import uuid
from typing import Literal

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

from app.models.identity import Role, User, UserRole

UserPickerType = Literal["internal", "portal", "any"]


async def list_picker_users(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    user_type: UserPickerType,
    role_id: uuid.UUID | None = None,
    caller_vendor_id: uuid.UUID | None = None,
) -> list[User]:
    """caller_vendor_id scopes the portal half of the pool to one vendor —
    pass the requesting caller's own vendor_id from the picker endpoint (so a
    portal caller never sees another vendor's people), or None when there is
    no caller identity to scope by (server-side validation of an already-
    submitted value checks it against the field's full declared pool, not
    against whoever happens to be submitting)."""
    stmt = select(User).where(User.tenant_id == tenant_id, User.status == "active")

    if user_type == "internal":
        stmt = stmt.where(User.vendor_id.is_(None))
    elif user_type == "portal":
        stmt = stmt.where(User.vendor_id.is_not(None))
        if caller_vendor_id is not None:
            stmt = stmt.where(User.vendor_id == caller_vendor_id)
    elif caller_vendor_id is not None:
        # "any", scoped to a portal caller: their own vendor's portal users, plus every internal user.
        stmt = stmt.where((User.vendor_id.is_(None)) | (User.vendor_id == caller_vendor_id))

    if role_id is not None:
        holders = select(UserRole.user_id).join(Role, Role.id == UserRole.role_id).where(
            UserRole.role_id == role_id, Role.tenant_id == tenant_id
        )
        stmt = stmt.where(User.id.in_(holders))

    return list((await db.execute(stmt)).scalars().all())
