"""
AI SLO REST API
===============
ADR-087 Phase 6 自我治理閉環 — AI 決策品質 SLO 查詢端點

Endpoints:
  GET /api/v1/ai/slo  — 取得最新 SLO 計算結果（含 Redis 快取）

設計原則:
- 優先讀 Service 層快取（TTL 5min），快取失效才重算
- 計算失敗 → 保守回傳 any_violated=True（由 AiSloCalculator 處理）
- 強制重算：?force_refresh=true
- Router 層不直接存取 Redis（leWOOOgo 積木化鐵律）

2026-04-15 ogt + Claude Sonnet 4.6（亞太）: Phase 6 初始建立
"""

from __future__ import annotations

import structlog
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel, Field

from src.services.adr100_remediation_service import (
    RemediationMode,
    RemediationNotFoundError,
    get_adr100_remediation_service,
)
from src.services.adr100_slo_status_service import get_adr100_slo_status_service
from src.services.ai_slo_calculator import AiSloCalculator

logger = structlog.get_logger(__name__)

router = APIRouter()


class RemediationPreviewRequest(BaseModel):
    """ADR-100 remediation preview request."""

    work_item_id: str = Field(min_length=1)
    mode: RemediationMode = "auto"


class RemediationDryRunRequest(BaseModel):
    """ADR-100 remediation dry-run request."""

    work_item_id: str = Field(min_length=1)
    mode: RemediationMode = "auto"


class RemediationApprovalRequest(BaseModel):
    """ADR-100 record-only approval request."""

    work_item_id: str = Field(min_length=1)
    mode: RemediationMode = "approval"


@router.get("/ai/slo")
async def get_ai_slo(
    force_refresh: bool = Query(False, description="忽略快取，強制重算"),
) -> dict:
    """
    取得 AI 決策品質 SLO 最新結果。

    優先讀 Redis 快取（TTL 5min）；force_refresh=true 則強制重算並更新快取。

    Response:
        calculated_at   ISO 時間戳
        window_days     計算視窗（天）
        any_violated    是否有任何 SLO 違反
        cache_hit       是否命中快取
        metrics[]       三大 SLO 指標明細
    """
    calc = AiSloCalculator()

    if not force_refresh:
        cached = await calc.get_cached_report()
        if cached:
            data = cached.to_dict()
            data["cache_hit"] = True
            data["adr100"] = await get_adr100_slo_status_service().fetch_report()
            return data

    report = await calc.run()
    data = report.to_dict()
    data["cache_hit"] = False
    data["adr100"] = await get_adr100_slo_status_service().fetch_report()
    return data


@router.get("/ai/slo/remediation/preview")
async def preview_ai_slo_remediation(
    work_item_id: str = Query(..., min_length=1),
    mode: RemediationMode = Query("auto"),
) -> dict:
    """Preview the safe remediation plan for one ADR-100 queue item."""

    try:
        return await get_adr100_remediation_service().preview(work_item_id, mode)
    except RemediationNotFoundError as exc:
        raise HTTPException(status_code=404, detail="remediation_work_item_not_found") from exc


@router.post("/ai/slo/remediation/preview")
async def preview_ai_slo_remediation_post(request: RemediationPreviewRequest) -> dict:
    """POST variant for clients that prefer JSON bodies."""

    try:
        return await get_adr100_remediation_service().preview(
            request.work_item_id,
            request.mode,
        )
    except RemediationNotFoundError as exc:
        raise HTTPException(status_code=404, detail="remediation_work_item_not_found") from exc


@router.post("/ai/slo/remediation/dry-run")
async def dry_run_ai_slo_remediation(request: RemediationDryRunRequest) -> dict:
    """Run a read-only ADR-100 remediation dry-run."""

    try:
        return await get_adr100_remediation_service().dry_run(
            request.work_item_id,
            request.mode,
        )
    except RemediationNotFoundError as exc:
        raise HTTPException(status_code=404, detail="remediation_work_item_not_found") from exc


@router.post("/ai/slo/remediation/approval-request")
async def create_ai_slo_remediation_approval_request(
    request: RemediationApprovalRequest,
) -> dict:
    """Create a record-only approval request for ADR-100 remediation."""

    try:
        return await get_adr100_remediation_service().create_approval_request(
            request.work_item_id,
            request.mode,
        )
    except RemediationNotFoundError as exc:
        raise HTTPException(status_code=404, detail="remediation_work_item_not_found") from exc


@router.get("/ai/slo/remediation/history")
async def list_ai_slo_remediation_history(
    limit: int = Query(50, ge=1, le=200),
    incident_id: str | None = Query(default=None, min_length=1),
    work_item_id: str | None = Query(default=None, min_length=1),
) -> dict:
    """List durable ADR-100 remediation dry-run history from alert_operation_log."""

    return await get_adr100_remediation_service().history(
        limit=limit,
        incident_id=incident_id,
        work_item_id=work_item_id,
    )
