"""后台上游资源操作审计。"""
from fastapi import APIRouter, Body, Depends, HTTPException, Query
from pydantic import BaseModel, Field
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.deps import require_role
from app.database import get_db
from app.models.order import Order
from app.models.upstream_action_log import UpstreamActionLog
from app.models.user import User
from app.schemas.common import ApiResponse
from app.services import upstream_action_service

router = APIRouter()
_admin = require_role("admin", "super_admin")


class ActionRemarkBody(BaseModel):
    remark: str | None = Field(None, max_length=255)


async def _get_action_for_update(db: AsyncSession, action_id: int) -> UpstreamActionLog:
    result = await db.execute(
        select(UpstreamActionLog)
        .where(UpstreamActionLog.id == action_id)
        .with_for_update()
    )
    item = result.scalar_one_or_none()
    if not item:
        raise HTTPException(status_code=404, detail="资源操作记录不存在")
    return item


@router.get("", response_model=ApiResponse)
async def list_upstream_actions(
    keyword: str | None = Query(None),
    status: str | None = Query(None),
    source: str | None = Query(None),
    action_type: str | None = Query(None),
    user_id: int | None = Query(None),
    order_id: int | None = Query(None),
    instance_id: int | None = Query(None),
    limit: int = Query(100, ge=1, le=300),
    offset: int = Query(0, ge=0),
    db: AsyncSession = Depends(get_db),
    _: User = Depends(_admin),
):
    stmt = (
        select(UpstreamActionLog)
        .order_by(UpstreamActionLog.id.desc())
        .limit(limit)
        .offset(offset)
    )
    if status:
        stmt = stmt.where(UpstreamActionLog.status == status)
    if source:
        stmt = stmt.where(UpstreamActionLog.source == source)
    if action_type:
        stmt = stmt.where(UpstreamActionLog.action_type == action_type)
    if user_id:
        stmt = stmt.where(UpstreamActionLog.user_id == user_id)
    if order_id:
        stmt = stmt.where(UpstreamActionLog.order_id == order_id)
    if instance_id:
        stmt = stmt.where(UpstreamActionLog.instance_id == instance_id)
    if keyword:
        like = f"%{keyword}%"
        order_ids = select(Order.id).where(Order.out_order_no.like(like))
        stmt = stmt.where(
            or_(
                UpstreamActionLog.action_type.like(like),
                UpstreamActionLog.resource_id.like(like),
                UpstreamActionLog.request_path.like(like),
                UpstreamActionLog.error_message.like(like),
                UpstreamActionLog.order_id.in_(order_ids),
            )
        )

    result = await db.execute(stmt)
    logs = list(result.scalars().all())

    user_ids = {int(item.user_id) for item in logs if item.user_id}
    order_ids = {int(item.order_id) for item in logs if item.order_id}
    users: dict[int, User] = {}
    orders: dict[int, Order] = {}
    if user_ids:
        user_result = await db.execute(select(User).where(User.id.in_(user_ids)))
        users = {int(item.id): item for item in user_result.scalars().all()}
    if order_ids:
        order_result = await db.execute(select(Order).where(Order.id.in_(order_ids)))
        orders = {int(item.id): item for item in order_result.scalars().all()}

    data = []
    for item in logs:
        row = upstream_action_service.serialize_action_log(item)
        user = users.get(int(item.user_id)) if item.user_id else None
        order = orders.get(int(item.order_id)) if item.order_id else None
        row["username"] = user.username if user else None
        row["order_no"] = order.out_order_no if order else None
        data.append(row)
    return ApiResponse(data=data)


@router.post("/sync", response_model=ApiResponse)
async def sync_upstream_actions(
    db: AsyncSession = Depends(get_db),
    _: User = Depends(_admin),
):
    summary = await upstream_action_service.sync_pending_actions(db, limit=200)
    return ApiResponse(data=summary, message="上游任务同步完成")


@router.post("/{action_id}/sync", response_model=ApiResponse)
async def sync_one_upstream_action(
    action_id: int,
    db: AsyncSession = Depends(get_db),
    _: User = Depends(_admin),
):
    item = await _get_action_for_update(db, action_id)
    status = await upstream_action_service.sync_action(db, item)
    return ApiResponse(
        data=upstream_action_service.serialize_action_log(item),
        message=f"资源操作已同步：{status}",
    )


@router.post("/{action_id}/retry", response_model=ApiResponse)
async def retry_upstream_action(
    action_id: int,
    body: ActionRemarkBody | None = Body(None),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(_admin),
):
    item = await _get_action_for_update(db, action_id)
    result = await upstream_action_service.retry_action(
        db,
        item,
        admin_user_id=current_user.id,
        remark=body.remark if body else None,
    )
    return ApiResponse(data=result, message="重试请求已提交")


@router.post("/{action_id}/mark-handled", response_model=ApiResponse)
async def mark_upstream_action_handled(
    action_id: int,
    body: ActionRemarkBody | None = Body(None),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(_admin),
):
    item = await _get_action_for_update(db, action_id)
    await upstream_action_service.mark_action_manual_handled(
        db,
        item,
        admin_user_id=current_user.id,
        remark=body.remark if body else None,
    )
    return ApiResponse(data=upstream_action_service.serialize_action_log(item), message="已标记人工处理完成")


@router.post("/{action_id}/ignore", response_model=ApiResponse)
async def ignore_upstream_action(
    action_id: int,
    body: ActionRemarkBody | None = Body(None),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(_admin),
):
    item = await _get_action_for_update(db, action_id)
    await upstream_action_service.mark_action_ignored(
        db,
        item,
        admin_user_id=current_user.id,
        remark=body.remark if body else None,
    )
    return ApiResponse(data=upstream_action_service.serialize_action_log(item), message="已标记无需处理")
