"""后台公告管理路由。"""
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.deps import require_role
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()
_admin = require_role("admin", "super_admin")


class AnnouncementCreate(BaseModel):
    title: str = Field(..., min_length=1, max_length=128)
    content: str = Field(..., min_length=1)
    category: str = Field("announcement", max_length=24)
    target_type: str = Field("all", pattern=r"^(all|specific)$")
    target_user_ids: list[int] | None = None


class NotificationBroadcastCreate(BaseModel):
    title: str = Field(..., min_length=1, max_length=128)
    content: str = Field(..., min_length=1)
    category: str = Field("system", max_length=24)
    level: str = Field("info", pattern=r"^(info|success|warning|error|urgent)$")
    target_type: str = Field("all", pattern=r"^(all|specific|role|member_level|agent)$")
    target_user_ids: list[int] | None = None
    target_role: str | None = Field(None, pattern=r"^(user|admin|super_admin)$")
    target_member_level_ids: list[int] | None = None
    active_agents_only: bool = True
    action_label: str | None = Field(None, max_length=40)
    action_url: str | None = Field(None, max_length=256)


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


@router.post("", response_model=ApiResponse)
async def create_announcement(
    body: AnnouncementCreate,
    admin: User = Depends(_admin),
    db: AsyncSession = Depends(get_db),
):
    if body.target_type == "specific" and not body.target_user_ids:
        raise HTTPException(status_code=400, detail="指定用户公告需要至少一个用户ID")
    item = await notification_service.publish_announcement(
        db,
        title=body.title,
        content=body.content,
        category=body.category,
        target_type=body.target_type,
        target_user_ids=body.target_user_ids,
        created_by=admin.id,
    )
    return ApiResponse(
        data=notification_service.admin_announcement_to_dict(item),
        message="公告已发布",
    )


@router.post("/notifications", response_model=ApiResponse)
async def broadcast_notification(
    body: NotificationBroadcastCreate,
    admin: User = Depends(_admin),
    db: AsyncSession = Depends(get_db),
):
    if body.target_type == "specific" and not body.target_user_ids:
        raise HTTPException(status_code=400, detail="指定用户群发需要至少一个用户ID")
    if body.target_type == "role" and not body.target_role:
        raise HTTPException(status_code=400, detail="按角色群发需要选择角色")
    if body.target_type == "member_level" and not body.target_member_level_ids:
        raise HTTPException(status_code=400, detail="按会员等级群发需要至少一个等级ID")
    sender_name = admin.nickname or admin.username or f"管理员#{admin.id}"
    data = await notification_service.broadcast_notification(
        db,
        target_type=body.target_type,
        target_user_ids=body.target_user_ids,
        target_role=body.target_role,
        target_member_level_ids=body.target_member_level_ids,
        active_agents_only=body.active_agents_only,
        title=body.title,
        content=body.content,
        category=body.category,
        level=body.level,
        sender_id=admin.id,
        sender_name=sender_name,
        sender_type="admin",
        action_label=body.action_label,
        action_url=body.action_url,
    )
    return ApiResponse(data=data, message="站内信已发送")


@router.delete("/{announcement_id}", response_model=ApiResponse)
async def delete_announcement(
    announcement_id: int,
    _admin: User = Depends(_admin),
    db: AsyncSession = Depends(get_db),
):
    ok = await notification_service.delete_announcement(db, announcement_id)
    return ApiResponse(data={"ok": ok})
