"""
Auto Repair API Router - #8 自動升級決策
========================================
自動修復評估與執行 API 端點

Phase 8.2: API Router 實作
建立時間: 2026-03-26 17:45 (台北時區)
建立者: Claude Code (#8 自動升級決策)

遵循 leWOOOgo 積木化原則:
- Router 層只做 HTTP 轉發
- 不直接存取 Redis/DB
- 業務邏輯委託給 Service 層
"""

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

from src.core.csrf import CSRFToken  # Phase 20: CSRF Protection

from src.services.auto_repair_service import (
    get_auto_repair_service,
)
from src.services.incident_service import get_incident_service

router = APIRouter(prefix="/auto-repair", tags=["Auto Repair"])


# =============================================================================
# Response Models
# =============================================================================


class EvaluateResponse(BaseModel):
    """評估自動修復回應"""

    can_auto_repair: bool = Field(description="是否可自動修復")
    playbook_id: str | None = Field(None, description="匹配的 Playbook ID")
    playbook_name: str | None = Field(None, description="Playbook 名稱")
    reason: str = Field(description="決策原因")
    risk_level: str = Field(default="MEDIUM", description="風險等級")
    blocked_by: str | None = Field(None, description="阻擋原因代碼")
    success_rate: float | None = Field(None, description="Playbook 成功率")
    total_executions: int | None = Field(None, description="Playbook 執行次數")


class ExecuteRequest(BaseModel):
    """執行自動修復請求"""

    incident_id: str = Field(description="Incident ID")
    playbook_id: str = Field(description="Playbook ID")
    force: bool = Field(
        default=False,
        description="強制執行 (跳過品質檢查，僅用於測試)",
    )


class ExecuteResponse(BaseModel):
    """執行自動修復回應"""

    success: bool = Field(description="是否執行成功")
    incident_id: str = Field(description="Incident ID")
    playbook_id: str = Field(description="Playbook ID")
    executed_steps: list[str] = Field(description="已執行的步驟")
    error: str | None = Field(None, description="錯誤訊息")
    execution_time_ms: int = Field(description="執行時間 (毫秒)")


# =============================================================================
# API Endpoints
# =============================================================================


@router.get("/evaluate/{incident_id}", response_model=EvaluateResponse)
async def evaluate_auto_repair(incident_id: str) -> EvaluateResponse:
    """
    評估 Incident 是否可自動修復

    決策條件:
    1. 有匹配的高品質 Playbook (成功率 >= 95%, 執行次數 >= 10)
    2. 動作風險等級 <= MEDIUM
    3. Incident 嚴重度 <= P2
    """
    # 取得 Incident
    incident_service = get_incident_service()
    incident = await incident_service.get_from_working_memory(incident_id)

    if not incident:
        raise HTTPException(
            status_code=404,
            detail=f"Incident {incident_id} not found",
        )

    # 評估
    auto_repair_service = get_auto_repair_service()
    decision = await auto_repair_service.evaluate_auto_repair(incident)

    return EvaluateResponse(
        can_auto_repair=decision.can_auto_repair,
        playbook_id=decision.playbook.playbook_id if decision.playbook else None,
        playbook_name=decision.playbook.name if decision.playbook else None,
        reason=decision.reason,
        risk_level=decision.risk_level.value if decision.risk_level else "MEDIUM",
        blocked_by=decision.blocked_by,
        success_rate=decision.playbook.success_rate if decision.playbook else None,
        total_executions=decision.playbook.total_executions if decision.playbook else None,
    )


@router.post("/execute", response_model=ExecuteResponse)
async def execute_auto_repair(request: ExecuteRequest, _csrf_token: CSRFToken) -> ExecuteResponse:  # Phase 20: CSRF Protection (驗證用，不需要使用值)
    """
    執行自動修復

    安全邊界:
    - 僅執行 LOW/MEDIUM 風險動作
    - HIGH/CRITICAL 自動跳過
    """
    # 取得 Incident
    incident_service = get_incident_service()
    incident = await incident_service.get_from_working_memory(request.incident_id)

    if not incident:
        raise HTTPException(
            status_code=404,
            detail=f"Incident {request.incident_id} not found",
        )

    # 取得 Playbook
    from src.services.playbook_service import get_playbook_service

    playbook_service = get_playbook_service()
    playbook = await playbook_service.get_by_id(request.playbook_id)

    if not playbook:
        raise HTTPException(
            status_code=404,
            detail=f"Playbook {request.playbook_id} not found",
        )

    # 安全檢查 (除非 force=True)
    if not request.force:
        auto_repair_service = get_auto_repair_service()
        decision = await auto_repair_service.evaluate_auto_repair(incident)

        if not decision.can_auto_repair:
            raise HTTPException(
                status_code=400,
                detail=f"Auto repair not allowed: {decision.reason}",
            )

        if decision.playbook and decision.playbook.playbook_id != request.playbook_id:
            raise HTTPException(
                status_code=400,
                detail=f"Playbook mismatch: expected {decision.playbook.playbook_id}",
            )

    # 執行
    auto_repair_service = get_auto_repair_service()
    result = await auto_repair_service.execute_auto_repair(incident, playbook)

    return ExecuteResponse(
        success=result.success,
        incident_id=result.incident_id,
        playbook_id=result.playbook_id,
        executed_steps=result.executed_steps,
        error=result.error,
        execution_time_ms=result.execution_time_ms,
    )


@router.get("/stats")
async def get_auto_repair_stats() -> dict:
    """
    取得自動修復統計

    返回:
    - 高品質 Playbook 數量
    - 自動修復執行次數
    - 成功率
    """
    from src.models.playbook import PlaybookStatus
    from src.services.playbook_service import get_playbook_service

    playbook_service = get_playbook_service()
    playbooks, total = await playbook_service.list_playbooks(
        status=PlaybookStatus.APPROVED,
        limit=100,
    )

    high_quality_count = sum(1 for p in playbooks if p.is_high_quality)
    total_executions = sum(p.total_executions for p in playbooks)
    total_success = sum(p.success_count for p in playbooks)

    # 2026-04-07 Claude Code: Sprint 4 C2 — 加入處置分佈摘要
    # P0-2 Fix: 呼叫 Service 層封裝方法
    disposition_summary = {"auto_repair": 0, "human_approved": 0, "manual_resolved": 0, "cold_start_trust": 0, "total": 0}
    try:
        from src.services.anomaly_counter import get_anomaly_counter
        counter = get_anomaly_counter()
        disposition_summary, _ = await counter.get_all_disposition_stats()
    except Exception:
        pass

    total_disp = disposition_summary["total"]
    auto_cnt = disposition_summary["auto_repair"] + disposition_summary["cold_start_trust"]

    return {
        "approved_playbooks": len(playbooks),
        "high_quality_playbooks": high_quality_count,
        "total_executions": total_executions,
        "overall_success_rate": total_success / total_executions if total_executions > 0 else 0.0,
        "auto_repair_eligible": high_quality_count > 0,
        "disposition_summary": {
            **disposition_summary,
            "auto_rate": auto_cnt / total_disp if total_disp > 0 else 0.0,
        },
    }


# =============================================================================
# History Models & Endpoint
# 2026-04-06 Claude Code: Sprint 3 T_frontend — 修復歷史記錄 API
# =============================================================================


class RepairHistoryItem(BaseModel):
    """修復歷史記錄項目"""

    id: str
    incident_id: str
    playbook_id: str
    playbook_name: str
    action_type: str  # "kubectl" | "ssh_command" | "manual"
    uri_scheme: str   # "kubectl://" | "openclaw://" | "ansible://"
    command: str
    status: str       # "success" | "failed" | "pending_approval" | "running"
    executed_at: str
    duration_ms: int | None = None
    error: str | None = None
    rag_confidence: float | None = None


class RepairHistoryResponse(BaseModel):
    """修復歷史記錄回應"""

    count: int
    items: list[RepairHistoryItem]


@router.get("/history", response_model=RepairHistoryResponse)
async def get_repair_history(
    limit: int = Query(20, ge=1, le=100),
) -> RepairHistoryResponse:
    """
    取得修復歷史記錄。
    從 incidents (working memory) 推導，回傳有 auto_repair 活動的事件。
    2026-04-06 Claude Code: Sprint 3 T_frontend
    """
    try:
        incident_service = get_incident_service()
        all_incidents = await incident_service.get_active_incidents()

        items: list[RepairHistoryItem] = []
        for incident in all_incidents:
            fs = incident.frequency_stats
            if fs is None or fs.auto_repair_count == 0:
                continue

            # 從 frequency_stats 推導修復狀態
            if fs.last_repair_success is True:
                status = "success"
            elif fs.last_repair_success is False:
                status = "failed"
            else:
                status = "running"

            action = fs.last_repair_action or "kubectl rollout restart"
            # 推導 action_type 和 uri_scheme
            if action.startswith("kubectl"):
                action_type = "kubectl"
                uri_scheme = "kubectl://"
            elif action.startswith("ssh") or action.startswith("ansible"):
                action_type = "ssh_command"
                uri_scheme = "ansible://"
            else:
                action_type = "manual"
                uri_scheme = "openclaw://"

            items.append(RepairHistoryItem(
                id=f"hist-{incident.incident_id}",
                incident_id=incident.incident_id,
                playbook_id="unknown",
                playbook_name=action,
                action_type=action_type,
                uri_scheme=uri_scheme,
                command=action,
                status=status,
                executed_at=incident.updated_at.isoformat(),
                duration_ms=None,
                error=None,
                rag_confidence=None,
            ))

        # 最多回傳 limit 筆，newest first (updated_at 已是活躍事件，先按 ID 截斷)
        items = items[:limit]

        return RepairHistoryResponse(count=len(items), items=items)

    except Exception:
        # 任何錯誤都回傳空列表，不中斷前端
        return RepairHistoryResponse(count=0, items=[])
