from fastapi import APIRouter, Depends
from sqlalchemy import func
from sqlalchemy.orm import Session

from auth import get_current_user
from database import get_db
from models import User, WordBookEntry
from schemas import (
    ActiveBookOut,
    BookPracticeSettingsOut,
    BookPracticeSettingsUpdate,
    SetActiveBookRequest,
    WordBookDetailOut,
    WordBookOut,
    WordBookProgressOut,
    WordBookUnitOut,
)
from services.book_service import book_service

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


def _active_out(db: Session, user: User, book) -> ActiveBookOut:
    progress = book_service.book_progress(db, user, book.id)
    settings = book_service.practice_settings_dict(db, user, book)
    return ActiveBookOut(
        book=WordBookOut.model_validate(book),
        progress=WordBookProgressOut(**progress),
        settings=BookPracticeSettingsOut(**settings),
    )


@router.get("", response_model=list[WordBookOut])
def list_books(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    return book_service.list_books(db)


@router.get("/settings", response_model=BookPracticeSettingsOut)
def get_book_practice_settings(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    book = book_service.get_active_book(db, current_user)
    if not book:
        from fastapi import HTTPException

        raise HTTPException(status_code=400, detail="请先在词书设置中选择词书")
    data = book_service.practice_settings_dict(db, current_user, book)
    return BookPracticeSettingsOut(**data)


@router.patch("/settings", response_model=ActiveBookOut)
def update_book_practice_settings(
    data: BookPracticeSettingsUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    book = book_service.get_active_book(db, current_user)
    if data.book_id:
        book = book_service.activate_book(db, current_user, data.book_id)
    elif not book:
        from fastapi import HTTPException

        raise HTTPException(status_code=400, detail="请先选择词书")
    payload = data.model_dump(exclude_unset=True, exclude={"book_id"})
    if payload:
        book_service.update_practice_settings(db, current_user, book.id, payload)
    return _active_out(db, current_user, book)


@router.get("/active", response_model=ActiveBookOut)
def get_active_book(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    book = book_service.get_active_book(db, current_user)
    if not book:
        return ActiveBookOut(book=None, progress=None, settings=None)
    return _active_out(db, current_user, book)


@router.post("/active", response_model=ActiveBookOut)
def set_active_book(
    data: SetActiveBookRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    book = book_service.activate_book(db, current_user, data.book_id)
    return _active_out(db, current_user, book)


@router.get("/{book_id}", response_model=WordBookDetailOut)
def get_book_detail(
    book_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    book = book_service.get_book(db, book_id)
    rows = (
        db.query(
            WordBookEntry.unit,
            WordBookEntry.unit_title,
            func.count(WordBookEntry.id),
        )
        .filter(WordBookEntry.book_id == book.id)
        .group_by(WordBookEntry.unit, WordBookEntry.unit_title)
        .order_by(WordBookEntry.unit.asc())
        .all()
    )
    units = [WordBookUnitOut(unit=r[0], title=r[1], word_count=r[2]) for r in rows]
    return WordBookDetailOut(
        **WordBookOut.model_validate(book).model_dump(),
        units=units,
    )
