"""Модуль работы с жанрами"""

from fastapi import APIRouter, Depends, HTTPException, Path, status
from sqlmodel import Session, select

from library_service.auth import RequireStaff
from library_service.models.db import Book, Genre, GenreBookLink
from library_service.models.dto import (
    BookRead,
    GenreCreate,
    GenreList,
    GenreRead,
    GenreUpdate,
    GenreWithBooks,
)
from library_service.settings import get_session


router = APIRouter(prefix="/genres", tags=["genres"])


@router.post(
    "/",
    response_model=GenreRead,
    summary="Создать жанр",
    description="Добавляет жанр книг в систему",
)
def create_genre(
    current_user: RequireStaff,
    genre: GenreCreate,
    session: Session = Depends(get_session),
):
    """Создает новый жанр в системе"""
    db_genre = Genre(**genre.model_dump())
    session.add(db_genre)
    session.commit()
    session.refresh(db_genre)
    return GenreRead(**db_genre.model_dump())


@router.get(
    "/",
    response_model=GenreList,
    summary="Получить список жанров",
    description="Возвращает список всех жанров в системе",
)
def read_genres(session: Session = Depends(get_session)):
    """Возвращает список всех жанров"""
    genres = session.exec(select(Genre)).all()
    return GenreList(
        genres=[GenreRead(**genre.model_dump()) for genre in genres], total=len(genres)
    )


@router.get(
    "/{genre_id}",
    response_model=GenreWithBooks,
    summary="Получить информацию о жанре",
    description="Возвращает информацию о жанре и книгах с ним",
)
def get_genre(
    genre_id: int = Path(..., description="ID жанра (целое число, > 0)", gt=0),
    session: Session = Depends(get_session),
):
    """Возвращает информацию о жанре и книгах с ним"""
    genre = session.get(Genre, genre_id)
    if not genre:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Genre not found",
        )

    books = session.exec(
        select(Book).join(GenreBookLink).where(GenreBookLink.genre_id == genre_id)
    ).all()

    book_reads = [BookRead(**book.model_dump()) for book in books]

    genre_data = genre.model_dump()
    genre_data["books"] = book_reads

    return GenreWithBooks(**genre_data)


@router.put(
    "/{genre_id}",
    response_model=GenreRead,
    summary="Обновить информацию о жанре",
    description="Обновляет информацию о жанре в системе",
)
def update_genre(
    current_user: RequireStaff,
    genre: GenreUpdate,
    genre_id: int = Path(..., description="ID жанра (целое число, > 0)", gt=0),
    session: Session = Depends(get_session),
):
    """Обновляет информацию о жанре"""
    db_genre = session.get(Genre, genre_id)
    if not db_genre:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Genre not found",
        )

    update_data = genre.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_genre, field, value)

    session.commit()
    session.refresh(db_genre)
    return GenreRead(**db_genre.model_dump())


@router.delete(
    "/{genre_id}",
    response_model=GenreRead,
    summary="Удалить жанр",
    description="Удаляет жанр из системы",
)
def delete_genre(
    current_user: RequireStaff,
    genre_id: int = Path(..., description="ID жанра (целое число, > 0)", gt=0),
    session: Session = Depends(get_session),
):
    """Удаляет жанр из системы"""
    genre = session.get(Genre, genre_id)
    if not genre:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Genre not found",
        )

    genre_read = GenreRead(**genre.model_dump())
    session.delete(genre)
    session.commit()
    return genre_read
