"""笔记 API"""

import uuid

from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.permissions import get_current_user
from app.db import get_db
from app.models.interaction import UserNote
from app.models.literature import GlobalLiterature
from app.models.user import User

router = APIRouter()


def uid(u: dict) -> uuid.UUID:
    return uuid.UUID(u["sub"])


@router.get("/mine", summary="我的笔记")
async def list_my_notes(
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    q: str = Query("", description="搜索关键词"),
):
    """获取当前用户最近的笔记，含文献标题、作者名。支持按内容搜索。"""
    user_uuid = uid(user)

    total_q = select(func.count(UserNote.id)).where(UserNote.user_id == user_uuid)
    if q.strip():
        total_q = total_q.where(UserNote.content.ilike(f"%{q.strip()}%"))
    total = (await db.execute(total_q)).scalar() or 0

    query = (
        select(UserNote, GlobalLiterature.title, GlobalLiterature.pmid)
        .join(GlobalLiterature, UserNote.literature_id == GlobalLiterature.id, isouter=True)
        .where(UserNote.user_id == user_uuid)
    )
    if q.strip():
        query = query.where(UserNote.content.ilike(f"%{q.strip()}%"))
    query = query.order_by(UserNote.created_at.desc()).offset((page - 1) * page_size).limit(page_size)

    rows = (await db.execute(query)).all()
    # 当前用户的信息作为作者名
    me = await db.execute(select(User.display_name).where(User.id == user_uuid))
    my_name = me.scalar()
    items = [
        NoteResponse(
            id=str(n.id), literature_id=str(n.literature_id),
            pmid=pmid, literature_title=title or "未知文献",
            content=n.content, quote_text=n.quote_text, is_private=n.is_private,
            author_name=my_name,
            created_at=n.created_at.isoformat() if n.created_at else None,
            updated_at=n.updated_at.isoformat() if n.updated_at else None,
        )
        for n, title, pmid in rows
    ]
    return {"items": items, "total": total}


class NoteCreate(BaseModel):
    content: str
    quote_text: str | None = None
    is_private: bool = True


class NoteUpdate(BaseModel):
    content: str | None = None
    quote_text: str | None = None
    is_private: bool | None = None


class NoteResponse(BaseModel):
    id: str
    literature_id: str
    literature_title: str | None = None
    pmid: int | None = None
    content: str
    quote_text: str | None = None
    is_private: bool
    author_name: str | None = None
    created_at: str | None = None
    updated_at: str | None = None


@router.get("/literature/{pmid}", response_model=list[NoteResponse], summary="文献笔记")
async def list_notes(pmid: int, db: AsyncSession = Depends(get_db), user: dict = Depends(get_current_user)):
    lit = (await db.execute(select(GlobalLiterature.id, GlobalLiterature.title).where(GlobalLiterature.pmid == pmid))).first()
    if not lit:
        raise HTTPException(status_code=404, detail="Literature not found")

    result = await db.execute(
        select(UserNote, User.display_name)
        .join(User, UserNote.user_id == User.id)
        .where(UserNote.literature_id == lit.id, UserNote.user_id == uid(user))
        .order_by(UserNote.created_at.desc())
    )
    rows = result.all()
    return [
        NoteResponse(
            id=str(n.id), literature_id=str(n.literature_id),
            pmid=pmid, literature_title=lit.title,
            content=n.content, quote_text=n.quote_text, is_private=n.is_private,
            author_name=uname,
            created_at=n.created_at.isoformat() if n.created_at else None,
            updated_at=n.updated_at.isoformat() if n.updated_at else None,
        )
        for n, uname in rows
    ]


@router.post("/literature/{pmid}", response_model=NoteResponse, status_code=201, summary="创建笔记")
async def create_note(pmid: int, req: NoteCreate, db: AsyncSession = Depends(get_db), user: dict = Depends(get_current_user)):
    lit = (await db.execute(select(GlobalLiterature.id, GlobalLiterature.title).where(GlobalLiterature.pmid == pmid))).first()
    if not lit:
        raise HTTPException(status_code=404, detail="Literature not found")

    note = UserNote(user_id=uid(user), literature_id=lit.id, content=req.content, quote_text=req.quote_text, is_private=req.is_private)
    db.add(note)
    await db.commit()
    await db.refresh(note)
    return NoteResponse(
        id=str(note.id), literature_id=str(note.literature_id),
        pmid=pmid, literature_title=lit.title,
        content=note.content, quote_text=note.quote_text, is_private=note.is_private,
        created_at=note.created_at.isoformat() if note.created_at else None,
        updated_at=note.updated_at.isoformat() if note.updated_at else None,
    )


@router.put("/{note_id}", response_model=NoteResponse, summary="更新笔记")
async def update_note(note_id: str, req: NoteUpdate, db: AsyncSession = Depends(get_db), user: dict = Depends(get_current_user)):
    try:
        note_uuid = uuid.UUID(note_id)
    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid note ID")
    result = await db.execute(select(UserNote).where(UserNote.id == note_uuid, UserNote.user_id == uid(user)))
    note = result.scalar()
    if not note:
        raise HTTPException(status_code=404, detail="Note not found")

    if req.content is not None:
        note.content = req.content
    if req.quote_text is not None:
        note.quote_text = req.quote_text
    if req.is_private is not None:
        note.is_private = req.is_private
    await db.commit()
    await db.refresh(note)

    lit = await db.execute(select(GlobalLiterature.pmid, GlobalLiterature.title).where(GlobalLiterature.id == note.literature_id))
    lit_row = lit.first()
    return NoteResponse(
        id=str(note.id), literature_id=str(note.literature_id),
        pmid=lit_row.pmid if lit_row else None,
        literature_title=lit_row.title if lit_row else None,
        content=note.content, quote_text=note.quote_text, is_private=note.is_private,
        created_at=note.created_at.isoformat() if note.created_at else None,
        updated_at=note.updated_at.isoformat() if note.updated_at else None,
    )


@router.delete("/{note_id}", summary="删除笔记")
async def delete_note(note_id: str, db: AsyncSession = Depends(get_db), user: dict = Depends(get_current_user)):
    try:
        note_uuid = uuid.UUID(note_id)
    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid note ID")
    result = await db.execute(select(UserNote).where(UserNote.id == note_uuid, UserNote.user_id == uid(user)))
    note = result.scalar()
    if not note:
        raise HTTPException(status_code=404, detail="Note not found")
    await db.delete(note)
    await db.commit()
    return {"status": "deleted"}
