"""
Platform Runs API
==================
AwoooP Phase 4: POST /v1/platform/runs — Shadow mode run 建立
2026-05-04 ogt + Claude Sonnet 4.6（ADR-106/ADR-114）

禁止碰：
- /v1/incidents/ — legacy 路由
- /v1/webhooks/ — legacy 路由
- Telegram bot handler — legacy 維持

Shadow mode 保證（Phase 4）：
- 建立的 run 全部 is_shadow=True
- 不發送任何 user-visible response
- 不執行任何 destructive tool call
"""

from __future__ import annotations

import uuid
from typing import Any

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

from src.services.audit_sink import write_audit
from src.services.platform_runtime import create_run

router = APIRouter()


# ─────────────────────────────────────────────────────────────────────────────
# Request / Response models
# ─────────────────────────────────────────────────────────────────────────────

class CreateRunRequest(BaseModel):
    """POST /v1/platform/runs request body"""

    project_id: str = Field(..., description="租戶 ID")
    agent_id: str = Field(..., description="執行此 run 的 agent ID")
    trigger_type: str = Field(
        ...,
        pattern="^(channel_event|schedule|api|sub_agent|retry)$",
        description="觸發來源類型",
    )
    trigger_ref: str | None = Field(None, description="觸發來源 ref（channel_event_id 等）")
    input_payload: dict[str, Any] | None = Field(None, description="Run 輸入 payload")
    channel_type: str | None = Field(None, description="Channel 類型（idempotency 用）")
    provider_event_id: str | None = Field(
        None, max_length=256,
        description="Channel provider 原始事件 ID（idempotency 去重用）",
    )
    timeout_seconds: int = Field(600, ge=30, le=3600, description="Run 超時秒數")


class CreateRunResponse(BaseModel):
    """POST /v1/platform/runs response"""

    run_id: str
    is_duplicate: bool = Field(description="True = 冪等命中，返回既有 run_id")
    is_shadow: bool = Field(True, description="Phase 4 固定 True")
    message: str


# ─────────────────────────────────────────────────────────────────────────────
# Routes
# ─────────────────────────────────────────────────────────────────────────────

@router.post(
    "/runs",
    response_model=CreateRunResponse,
    status_code=status.HTTP_202_ACCEPTED,
    summary="建立 Platform Run（Shadow Mode）",
    description=(
        "AwoooP Phase 4 Shadow Mode：建立新 run，非同步執行。\n\n"
        "- `is_shadow=true`：不產生任何 user-visible response\n"
        "- `is_duplicate=true`：冪等命中，返回既有 run_id（不建立新 run）\n"
        "- provider_event_id + channel_type 構成冪等 key（24h 視窗）"
    ),
)
async def create_platform_run(
    request: CreateRunRequest,
) -> CreateRunResponse:
    """建立 shadow run。"""
    try:
        run_id, is_duplicate = await create_run(
            project_id=request.project_id,
            agent_id=request.agent_id,
            trigger_type=request.trigger_type,
            trigger_ref=request.trigger_ref,
            input_payload=request.input_payload,
            channel_type=request.channel_type,
            provider_event_id=request.provider_event_id,
            timeout_seconds=request.timeout_seconds,
        )
    except Exception as exc:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Run 建立失敗: {exc}",
        ) from exc

    # Audit log（非阻擋）
    await write_audit(
        project_id=request.project_id,
        action="run.created",
        resource_type="run",
        resource_id=str(run_id),
        details={
            "agent_id": request.agent_id,
            "trigger_type": request.trigger_type,
            "is_duplicate": is_duplicate,
            "is_shadow": True,
        },
    )

    return CreateRunResponse(
        run_id=str(run_id),
        is_duplicate=is_duplicate,
        is_shadow=True,
        message="Run 已接受（shadow mode）" if not is_duplicate else "冪等命中，返回既有 run_id",
    )


@router.get(
    "/runs/{run_id}",
    summary="查詢 Run 狀態",
)
async def get_run_status(
    run_id: str,
    project_id: str,
) -> dict[str, Any]:
    """查詢單一 run 的 FSM 狀態。"""
    from src.services.platform_runtime import get_run_status as _svc_get_run_status

    try:
        uid = uuid.UUID(run_id)
    except ValueError as exc:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=f"run_id 格式錯誤: {exc}",
        ) from exc

    result = await _svc_get_run_status(uid, project_id)
    if result is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"run {run_id!r} 不存在",
        )
    return result
