"""用户站内信路由。"""
from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.deps import get_current_user
from app.database import get_db
from app.models.user import User
from app.schemas.common import ApiResponse
from app.services import notification_service

router = APIRouter()


class NotificationBatchIds(BaseModel):
    ids: list[int] = Field(default_factory=list)


class NotificationArchiveBody(NotificationBatchIds):
    archived: bool = True


class NotificationHandledBody(NotificationBatchIds):
    handled: bool = True


class NotificationPreferenceUpdate(BaseModel):
    preferences: list[dict] = Field(default_factory=list)


@router.get("/unread-count", response_model=ApiResponse)
async def get_unread_count(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await notification_service.unread_count(db, current_user.id)
    return ApiResponse(data=data)


@router.get("/announcements", response_model=ApiResponse)
async def list_my_announcements(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    items, total = await notification_service.list_announcements(
        db, current_user.id, limit=limit, offset=offset
    )
    return ApiResponse(data={"items": items, "total": total})


@router.get("/preferences", response_model=ApiResponse)
async def get_preferences(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await notification_service.get_preferences(db, current_user.id)
    return ApiResponse(data=data)


@router.put("/preferences", response_model=ApiResponse)
async def update_preferences(
    body: NotificationPreferenceUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await notification_service.update_preferences(db, current_user.id, body.preferences)
    return ApiResponse(data=data)


@router.post("/announcements/{announcement_id}/read", response_model=ApiResponse)
async def read_announcement(
    announcement_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    ok = await notification_service.mark_announcement_read(db, current_user.id, announcement_id)
    return ApiResponse(data={"ok": ok})


@router.post("/read-all", response_model=ApiResponse)
async def read_all(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    count = await notification_service.mark_all_read(db, current_user.id)
    return ApiResponse(data={"count": count})


@router.get("", response_model=ApiResponse)
async def list_my_notifications(
    category: str | None = Query(None),
    level: str | None = Query(None),
    unread_only: bool = Query(False),
    important_only: bool = Query(False),
    archived_only: bool = Query(False),
    handled_state: str | None = Query(None, pattern=r"^(handled|unhandled)$"),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    items, total = await notification_service.list_notifications(
        db,
        current_user.id,
        category=category,
        level=level,
        unread_only=unread_only,
        important_only=important_only,
        archived_only=archived_only,
        handled_state=handled_state,
        limit=limit,
        offset=offset,
    )
    return ApiResponse(data={"items": items, "total": total})


@router.post("/batch/read", response_model=ApiResponse)
async def read_many(
    body: NotificationBatchIds,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    count = await notification_service.mark_many_read(db, current_user.id, body.ids)
    return ApiResponse(data={"count": count})


@router.post("/batch/delete", response_model=ApiResponse)
async def delete_many(
    body: NotificationBatchIds,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    count = await notification_service.delete_many_notifications(db, current_user.id, body.ids)
    return ApiResponse(data={"count": count})


@router.post("/batch/archive", response_model=ApiResponse)
async def archive_many(
    body: NotificationArchiveBody,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    count = await notification_service.set_many_archived(
        db, current_user.id, body.ids, archived=body.archived
    )
    return ApiResponse(data={"count": count})


@router.post("/batch/handled", response_model=ApiResponse)
async def handle_many(
    body: NotificationHandledBody,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    count = await notification_service.set_many_handled(
        db, current_user.id, body.ids, handled=body.handled
    )
    return ApiResponse(data={"count": count})


@router.post("/{notification_id}/read", response_model=ApiResponse)
async def read_one(
    notification_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    ok = await notification_service.mark_read(db, current_user.id, notification_id)
    return ApiResponse(data={"ok": ok})


@router.delete("/{notification_id}", response_model=ApiResponse)
async def delete_one(
    notification_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    ok = await notification_service.delete_notification(db, current_user.id, notification_id)
    return ApiResponse(data={"ok": ok})
