# -*- coding: utf-8 -*-
"""
管理端 — AI 监控后台路由。

端点清单（13 个，全部需要 JWT + admin 角色）：
- GET    /api/admin/ai/dashboard                — 总览统计
- GET    /api/admin/ai/trigger-jobs             — 调度任务分页列表
- GET    /api/admin/ai/trigger-jobs/{job_id}    — 调度任务详情
- POST   /api/admin/ai/trigger-jobs/{job_id}/retry — 手动重跑
- GET    /api/admin/ai/run-logs                 — 调用记录分页列表
- GET    /api/admin/ai/run-logs/{log_id}        — 调用记录详情
- POST   /api/admin/ai/cache/invalidate         — 缓存失效
- GET    /api/admin/ai/budget                   — Token 预算
- POST   /api/admin/ai/batch-run                — 创建批量执行（返回预估）
- POST   /api/admin/ai/batch-run/confirm        — 确认批量执行
- GET    /api/admin/ai/alerts                   — 告警列表
- POST   /api/admin/ai/alerts/{log_id}/ack      — 确认告警
- POST   /api/admin/ai/alerts/{log_id}/ignore   — 忽略告警

需求: A1.1, A2.1, A2.4, A3.1, A4.1, A4.3, A5.1, A6.1, A7.1, A7.3, A8.1, A8.2, A8.3, A9.1, A9.2, A9.3
"""

from __future__ import annotations

import logging
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query, status

from app.auth.dependencies import CurrentUser
from app.middleware.permission import require_permission
from app.schemas.admin_ai import (
    AlertActionResponse,
    AlertListResponse,
    BatchRunConfirm,
    BatchRunConfirmResponse,
    BatchRunEstimate,
    BatchRunRequest,
    BudgetResponse,
    CacheInvalidateRequest,
    CacheInvalidateResponse,
    DashboardResponse,
    RetryResponse,
    RunLogDetailResponse,
    RunLogListResponse,
    TriggerJobDetailResponse,
    TriggerJobListResponse,
)
from app.services.ai.admin_service import AdminAIService

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/admin/ai", tags=["admin-ai"])


# ── 模块级服务实例 ────────────────────────────────────────
_admin_svc = AdminAIService()


# ── 权限依赖 ──────────────────────────────────────────────


def _require_admin():
    """
    管理端依赖：要求 JWT status=approved 且角色包含 site_admin 或 tenant_admin。
    """

    async def _dependency(
        user: CurrentUser = Depends(require_permission()),
    ) -> CurrentUser:
        admin_roles = {"site_admin", "tenant_admin"}
        if not admin_roles.intersection(user.roles):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="需要管理员权限（site_admin 或 tenant_admin）",
            )
        return user

    return _dependency


# ── Dashboard ─────────────────────────────────────────────


@router.get("/dashboard", response_model=DashboardResponse)
async def get_dashboard(
    site_id: Optional[int] = Query(None, description="门店 ID 筛选"),
    user: CurrentUser = Depends(_require_admin()),
) -> DashboardResponse:
    """总览统计（支持 site_id 筛选）。"""
    data = await _admin_svc.get_dashboard(site_id=site_id)
    return DashboardResponse(**data)


# ── 调度任务 ──────────────────────────────────────────────


@router.get("/trigger-jobs", response_model=TriggerJobListResponse)
async def list_trigger_jobs(
    event_type: Optional[str] = Query(None),
    status_filter: Optional[str] = Query(None, alias="status"),
    site_id: Optional[int] = Query(None),
    date_from: Optional[str] = Query(None, description="起始日期 YYYY-MM-DD"),
    date_to: Optional[str] = Query(None, description="截止日期 YYYY-MM-DD"),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    user: CurrentUser = Depends(_require_admin()),
) -> TriggerJobListResponse:
    """调度任务分页列表。"""
    filters: dict = {}
    if event_type is not None:
        filters["event_type"] = event_type
    if status_filter is not None:
        filters["status"] = status_filter
    if site_id is not None:
        filters["site_id"] = site_id
    if date_from is not None:
        filters["date_from"] = date_from
    if date_to is not None:
        filters["date_to"] = date_to

    data = await _admin_svc.list_trigger_jobs(filters, page=page, page_size=page_size)
    return TriggerJobListResponse(**data)


@router.get("/trigger-jobs/{job_id}", response_model=TriggerJobDetailResponse)
async def get_trigger_job(
    job_id: int,
    user: CurrentUser = Depends(_require_admin()),
) -> TriggerJobDetailResponse:
    """调度任务详情。"""
    data = await _admin_svc.get_trigger_job(job_id)
    if data is None:
        raise HTTPException(status_code=404, detail="调度任务不存在")
    return TriggerJobDetailResponse(**data)


@router.post("/trigger-jobs/{job_id}/retry", response_model=RetryResponse)
async def retry_trigger_job(
    job_id: int,
    user: CurrentUser = Depends(_require_admin()),
) -> RetryResponse:
    """手动重跑：创建新 trigger_job（is_forced=true），异步执行。"""
    try:
        new_job_id = await _admin_svc.retry_trigger_job(job_id)
    except ValueError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
    return RetryResponse(trigger_job_id=new_job_id, status="pending")


# ── 调用记录 ──────────────────────────────────────────────


@router.get("/run-logs", response_model=RunLogListResponse)
async def list_run_logs(
    app_type: Optional[str] = Query(None),
    status_filter: Optional[str] = Query(None, alias="status"),
    trigger_type: Optional[str] = Query(None),
    site_id: Optional[int] = Query(None),
    date_from: Optional[str] = Query(None, description="起始日期 YYYY-MM-DD"),
    date_to: Optional[str] = Query(None, description="截止日期 YYYY-MM-DD"),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    user: CurrentUser = Depends(_require_admin()),
) -> RunLogListResponse:
    """调用记录分页列表。"""
    filters: dict = {}
    if app_type is not None:
        filters["app_type"] = app_type
    if status_filter is not None:
        filters["status"] = status_filter
    if trigger_type is not None:
        filters["trigger_type"] = trigger_type
    if site_id is not None:
        filters["site_id"] = site_id
    if date_from is not None:
        filters["date_from"] = date_from
    if date_to is not None:
        filters["date_to"] = date_to

    data = await _admin_svc.list_run_logs(filters, page=page, page_size=page_size)
    return RunLogListResponse(**data)


@router.get("/run-logs/{log_id}", response_model=RunLogDetailResponse)
async def get_run_log(
    log_id: int,
    user: CurrentUser = Depends(_require_admin()),
) -> RunLogDetailResponse:
    """调用记录详情（含完整 prompt/response/error，不脱敏）。"""
    data = await _admin_svc.get_run_log(log_id)
    if data is None:
        raise HTTPException(status_code=404, detail="调用记录不存在")
    return RunLogDetailResponse(**data)


# ── 缓存管理 ──────────────────────────────────────────────


@router.post("/cache/invalidate", response_model=CacheInvalidateResponse)
async def invalidate_cache(
    body: CacheInvalidateRequest,
    user: CurrentUser = Depends(_require_admin()),
) -> CacheInvalidateResponse:
    """批量缓存失效：将匹配条件的 ai_cache.status 设为 invalidated。"""
    affected = await _admin_svc.invalidate_cache(
        site_id=body.site_id,
        app_type=body.app_type,
        member_id=body.member_id,
    )
    return CacheInvalidateResponse(affected_count=affected)


# ── Token 预算 ────────────────────────────────────────────


@router.get("/budget", response_model=BudgetResponse)
async def get_budget(
    user: CurrentUser = Depends(_require_admin()),
) -> BudgetResponse:
    """Token 预算使用情况：日/月已用量、上限、百分比。"""
    data = await _admin_svc.get_budget()
    return BudgetResponse(**data)


# ── 批量执行 ──────────────────────────────────────────────


@router.post("/batch-run", response_model=BatchRunEstimate)
async def create_batch_run(
    body: BatchRunRequest,
    user: CurrentUser = Depends(_require_admin()),
) -> BatchRunEstimate:
    """创建批量执行请求，返回预估（不立即执行）。"""
    data = await _admin_svc.estimate_batch(
        app_types=body.app_types,
        member_ids=body.member_ids,
        site_id=body.site_id,
    )
    return BatchRunEstimate(**data)


@router.post("/batch-run/confirm", response_model=BatchRunConfirmResponse)
async def confirm_batch_run(
    body: BatchRunConfirm,
    user: CurrentUser = Depends(_require_admin()),
) -> BatchRunConfirmResponse:
    """确认批量执行，后台异步执行。"""
    try:
        await _admin_svc.confirm_batch(batch_id=body.batch_id)
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return BatchRunConfirmResponse(status="started")


# ── 告警管理 ──────────────────────────────────────────────


@router.get("/alerts", response_model=AlertListResponse)
async def list_alerts(
    alert_status: Optional[str] = Query(None, description="pending / acknowledged / ignored"),
    site_id: Optional[int] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    user: CurrentUser = Depends(_require_admin()),
) -> AlertListResponse:
    """告警列表（ai_run_logs WHERE status IN ('failed','timeout','circuit_open')）。"""
    data = await _admin_svc.list_alerts(
        alert_status=alert_status,
        site_id=site_id,
        page=page,
        page_size=page_size,
    )
    return AlertListResponse(**data)


@router.post("/alerts/{log_id}/ack", response_model=AlertActionResponse)
async def ack_alert(
    log_id: int,
    user: CurrentUser = Depends(_require_admin()),
) -> AlertActionResponse:
    """确认告警：alert_status → acknowledged。"""
    new_status = await _admin_svc.ack_alert(log_id)
    return AlertActionResponse(id=log_id, alert_status=new_status)


@router.post("/alerts/{log_id}/ignore", response_model=AlertActionResponse)
async def ignore_alert(
    log_id: int,
    user: CurrentUser = Depends(_require_admin()),
) -> AlertActionResponse:
    """忽略告警：alert_status → ignored。"""
    new_status = await _admin_svc.ignore_alert(log_id)
    return AlertActionResponse(id=log_id, alert_status=new_status)
