"""Профиль пользователя: сборка ответа, правка данных, аватар.

Переиспользуется `api/users.py` (свой профиль) и `api/admin.py` (карточка
профиля любого пользователя администратором) — правила одни и те же (задача
4c: «те же данные, редактирование по тем же правилам»).
"""

import uuid
from pathlib import Path

from fastapi import UploadFile
from sqlalchemy.ext.asyncio import AsyncSession

from models.team import Team
from models.user import User
from repositories.admin import TeamRepository
from services.avatars import delete_avatar, read_and_validate_avatar, save_avatar


class TeamNotFoundError(Exception):
    """Команда с указанным `team_id` не найдена."""


async def resolve_team_name(session: AsyncSession, team_id: uuid.UUID | None) -> str | None:
    """Имя команды пользователя (`None`, если команда не привязана или была удалена)."""
    if team_id is None:
        return None
    team = await session.get(Team, team_id)
    return team.name if team is not None else None


async def update_profile_fields(
    session: AsyncSession,
    user: User,
    *,
    name_user: str | None,
    team_id: uuid.UUID | None,
    team_id_is_set: bool,
) -> User:
    """Изменить ФИО и/или команду пользователя.

    `team_id_is_set` — поле присутствовало в теле запроса (в т.ч. явный
    `null`, различаем через `model_fields_set` на стороне роутера) — тот же
    приём, что и `summary_recipients`/`team_id` в других PATCH-эндпоинтах
    (`services/conferences.py`, `api/admin.py`). Email НЕ принимается —
    read-only поле профиля.
    """
    if name_user is not None:
        user.name_user = name_user
    if team_id_is_set:
        if team_id is not None and await TeamRepository(session).get(team_id) is None:
            raise TeamNotFoundError
        user.team_id = team_id
    return user


async def set_avatar(media_root: Path, user: User, file: UploadFile) -> User:
    """Загрузить, провалидировать и сохранить новый аватар пользователя.

    Бросает `AvatarTooLargeError`/`AvatarInvalidTypeError` (см. `services/avatars.py`).
    """
    content, ext = await read_and_validate_avatar(file)
    user.avatar_path = save_avatar(media_root, user.id, content, ext, old_path=user.avatar_path)
    return user


def clear_avatar(media_root: Path, user: User) -> None:
    """Удалить файл аватара пользователя с диска и очистить `avatar_path`."""
    delete_avatar(media_root, user.avatar_path)
    user.avatar_path = None
