"""Репозиторий доступа к таблице `users`."""

import uuid
from datetime import datetime

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

from models.user import User


class UserRepository:
    """Инкапсулирует SQL-запросы к пользователям."""

    def __init__(self, session: AsyncSession) -> None:
        self._session = session

    async def get_by_email(self, email: str) -> User | None:
        """Найти пользователя по email (регистр значим, как задано в БД)."""
        result = await self._session.execute(select(User).where(User.email == email))
        return result.scalar_one_or_none()

    async def get_by_id(self, user_id: uuid.UUID) -> User | None:
        """Найти пользователя по id."""
        return await self._session.get(User, user_id)

    async def create(
        self,
        *,
        email: str,
        name_user: str,
        password_hash: str,
        team_id: uuid.UUID | None = None,
        consent_version: int | None = None,
        consent_given_at: datetime | None = None,
    ) -> User:
        """Создать нового пользователя (role='user', email_verified=False по умолчанию).

        `consent_version`/`consent_given_at` — редакция регламента обработки
        персональных данных, с которой согласился пользователь, и время
        согласия; `None` у обоих, если согласие не запрашивалось (модуль
        выключен) — см. `services.auth.AuthService.register`.
        """
        user = User(
            email=email,
            name_user=name_user,
            password_hash=password_hash,
            team_id=team_id,
            consent_version=consent_version,
            consent_given_at=consent_given_at,
        )
        self._session.add(user)
        await self._session.flush()
        return user

    async def list_all(self) -> list[User]:
        """Список всех пользователей (для мультиселекта участников брони, без пагинации)."""
        result = await self._session.execute(select(User).order_by(User.name_user))
        return list(result.scalars().all())

    async def search(self, *, q: str | None, limit: int) -> list[User]:
        """Пикер участников конференции: без `q` — полный список (как `list_all`);
        с `q` — поиск по имени/email (`ILIKE`), ограниченный `limit`.
        """
        if not q:
            return await self.list_all()
        like = f"%{q}%"
        stmt = (
            select(User)
            .where(or_(User.name_user.ilike(like), User.email.ilike(like)))
            .order_by(User.name_user)
            .limit(limit)
        )
        result = await self._session.execute(stmt)
        return list(result.scalars().all())
