"""
Agent Teams API - Phase 9.5 多專家協作系統
==========================================

Endpoints:
- POST /api/v1/agents/analyze           - 觸發 Agent Teams 分析
- GET  /api/v1/agents/status/{task_id}  - 查詢分析狀態
- GET  /api/v1/agents/result/{task_id}  - 取得分析結果
- GET  /api/v1/agents/stream/{task_id}  - SSE 串流進度

Phase 9.4-9.5 核心功能:
1. ConsensusEngine 整合多專家意見
2. BackgroundTasks 執行長時間分析
3. Redis Working Memory 儲存結果
4. SSE 推送即時進度

Phase 17 技術債修復 (2026-03-26):
- Router 層不再直接存取 Redis
- 所有業務邏輯封裝至 AgentService
- 符合 leWOOOgo 積木化原則

統帥鐵律:
- 所有分析任務必須可追蹤 (task_id)
- 超過 60 秒的分析必須用 BackgroundTasks
- 結果必須存入 Redis (7 天 TTL)
"""

import asyncio
import json
from typing import Any

from fastapi import APIRouter, BackgroundTasks, HTTPException, status
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field

from src.core.logging import get_logger
from src.core.sse import get_publisher
from src.services.agent_service import (
    AgentService,
    TaskState,
    get_agent_service,
)

router = APIRouter(prefix="/agents", tags=["Agent Teams"])
logger = get_logger("awoooi.agents")


# =============================================================================
# Request/Response Models
# =============================================================================

class AnalyzeRequest(BaseModel):
    """分析請求"""
    incident_id: str | None = Field(
        None,
        description="現有 Incident ID (二選一)"
    )
    # 或直接提供 Incident 資訊
    severity: str | None = Field(
        None,
        description="事件嚴重度 (P0/P1/P2/P3)"
    )
    affected_services: list[str] | None = Field(
        None,
        description="受影響服務列表"
    )
    alert_names: list[str] | None = Field(
        None,
        description="告警名稱列表"
    )
    context: dict[str, Any] | None = Field(
        None,
        description="額外上下文"
    )


class AnalyzeResponse(BaseModel):
    """分析回應"""
    task_id: str
    status: str
    message: str
    estimated_seconds: int = 30


class TaskStatusResponse(BaseModel):
    """任務狀態回應"""
    task_id: str
    state: str
    progress: int  # 0-100
    current_step: str | None = None
    agents_completed: int = 0
    total_agents: int = 4
    started_at: str | None = None
    completed_at: str | None = None
    error: str | None = None


class TaskResultResponse(BaseModel):
    """任務結果回應"""
    task_id: str
    state: str
    consensus_id: str | None = None
    incident_id: str | None = None
    consensus_score: float | None = None
    recommended_action: str | None = None
    recommended_kubectl: str | None = None
    risk_level: str | None = None
    final_reasoning: str | None = None
    opinions: list[dict[str, Any]] | None = None
    dissenting_opinions: list[str] | None = None
    created_at: str | None = None


# =============================================================================
# Background Task Wrapper
# =============================================================================

async def _run_analysis_task(
    service: AgentService,
    task_id: str,
    incident_id: str,
) -> None:
    """
    背景任務包裝器

    從 AgentService 取得 Incident 並執行分析
    """
    incident = await service.get_incident(incident_id)
    if incident is None:
        logger.error("background_task_incident_not_found", incident_id=incident_id)
        return

    await service.run_analysis(task_id, incident)


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

@router.post(
    "/analyze",
    response_model=AnalyzeResponse,
    summary="觸發 Agent Teams 分析",
    description="""
    觸發多專家協作分析。

    可提供:
    - 現有 Incident ID (從 Redis 讀取)
    - 或直接提供事件資訊 (severity, affected_services, alert_names)

    分析在背景執行，使用 task_id 追蹤進度。

    專家團隊:
    - SRE Agent: 系統穩定性分析
    - Security Agent: 資安風險評估
    - Cost Agent: 成本效益分析
    - Performance Agent: 效能優化建議
    """,
)
async def analyze(
    request: AnalyzeRequest,
    background_tasks: BackgroundTasks,
) -> AnalyzeResponse:
    """
    觸發 Agent Teams 分析

    返回 task_id 用於追蹤進度
    """
    service = get_agent_service()

    # 取得或建立 Incident
    if request.incident_id:
        # 從 Redis 讀取現有 Incident
        incident = await service.get_incident(request.incident_id)

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

    elif request.severity and request.affected_services:
        # 建立臨時 Incident
        incident = service.create_adhoc_incident(
            severity=request.severity,
            affected_services=request.affected_services,
            alert_names=request.alert_names,
        )

    else:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Must provide either incident_id or (severity + affected_services)",
        )

    # 建立任務
    task_id = await service.create_analysis_task(incident, trigger="manual")

    # 加入背景任務
    background_tasks.add_task(
        service.run_analysis,
        task_id,
        incident,
    )

    logger.info(
        "agent_analysis_started",
        task_id=task_id,
        incident_id=incident.incident_id,
        severity=incident.severity.value,
    )

    return AnalyzeResponse(
        task_id=task_id,
        status="pending",
        message="Agent Teams 分析已啟動",
        estimated_seconds=30,
    )


@router.get(
    "/status/{task_id}",
    response_model=TaskStatusResponse,
    summary="查詢分析狀態",
    description="查詢 Agent Teams 分析任務的目前狀態與進度。",
)
async def get_status(task_id: str) -> TaskStatusResponse:
    """
    查詢任務狀態

    返回進度百分比與目前步驟
    """
    service = get_agent_service()
    task_data = await service.get_task_status(task_id)

    if task_data is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Task not found: {task_id}",
        )

    return TaskStatusResponse(
        task_id=task_id,
        state=task_data.get("state", "unknown"),
        progress=task_data.get("progress", 0),
        current_step=task_data.get("current_step"),
        agents_completed=task_data.get("agents_completed", 0),
        total_agents=task_data.get("total_agents", 4),
        started_at=task_data.get("started_at"),
        completed_at=task_data.get("completed_at"),
        error=task_data.get("error"),
    )


@router.get(
    "/result/{task_id}",
    response_model=TaskResultResponse,
    summary="取得分析結果",
    description="取得 Agent Teams 分析的完整結果，包含所有專家意見與共識決策。",
)
async def get_result(task_id: str) -> TaskResultResponse:
    """
    取得分析結果

    只有 COMPLETED 狀態才有完整結果
    """
    service = get_agent_service()
    task_data = await service.get_task_result(task_id)

    if task_data is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Task not found: {task_id}",
        )

    return TaskResultResponse(
        task_id=task_id,
        state=task_data.get("state", "unknown"),
        consensus_id=task_data.get("consensus_id"),
        incident_id=task_data.get("incident_id"),
        consensus_score=task_data.get("consensus_score"),
        recommended_action=task_data.get("recommended_action"),
        recommended_kubectl=task_data.get("recommended_kubectl"),
        risk_level=task_data.get("risk_level"),
        final_reasoning=task_data.get("final_reasoning"),
        opinions=task_data.get("opinions"),
        dissenting_opinions=task_data.get("dissenting_opinions"),
        created_at=task_data.get("completed_at"),
    )


@router.get(
    "/stream/{task_id}",
    summary="SSE 串流進度",
    description="透過 Server-Sent Events 即時接收分析進度更新。",
)
async def stream_progress(task_id: str) -> StreamingResponse:
    """
    SSE 串流分析進度

    客戶端可訂閱此端點接收即時更新
    """
    service = get_agent_service()

    # 驗證任務存在
    task_data = await service.get_task_status(task_id)
    if task_data is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Task not found: {task_id}",
        )

    async def generate():
        """SSE 串流生成器"""
        publisher = await get_publisher()
        client = await publisher.subscribe(
            topics=[f"agent_task:{task_id}"],
            metadata={"task_id": task_id},
        )

        try:
            # 發送初始狀態
            current_data = await service.get_task_status(task_id)
            if current_data:
                payload = json.dumps(
                    {"type": "status", **current_data},
                    ensure_ascii=False,
                )
                yield f"data: {payload}\n\n"

            # 串流後續更新
            async for event_str in publisher.stream(client):
                yield event_str

                # 檢查是否完成或失敗
                current_data = await service.get_task_status(task_id)
                if current_data:
                    final_states = [TaskState.COMPLETED.value, TaskState.FAILED.value]
                    if current_data.get("state") in final_states:
                        break

        except asyncio.CancelledError:
            logger.info("agent_stream_cancelled", task_id=task_id)
            raise
        finally:
            await publisher.unsubscribe(client.id)

    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no",
        },
    )


# =============================================================================
# Integration with Incident Flow
# =============================================================================

async def trigger_agent_analysis_for_incident(
    incident_id: str,
    background_tasks: BackgroundTasks,
) -> str | None:
    """
    整合點: 當 Incident 需要複雜決策時自動觸發 Agent Teams

    這個函數可被 incident_engine 或 webhooks 調用

    Returns:
        task_id if triggered, None if skipped
    """
    service = get_agent_service()

    task_id, incident = await service.trigger_for_incident(incident_id)

    if task_id is None:
        return None

    if incident is None:
        return None

    # 加入背景任務
    background_tasks.add_task(
        service.run_analysis,
        task_id,
        incident,
    )

    return task_id
