"""
Terminal API Router
===================
Phase 19.1 - Omni-Terminal SSE Endpoints

Hybrid SSE 模式:
- POST /terminal/intent → 提交意圖，取得 session_id
- GET /terminal/stream/{session_id} → SSE 串流訂閱
- POST /terminal/abort/{session_id} → 中斷執行
- GET /terminal/status/{session_id} → 查詢狀態

遵循 leWOOOgo 積木化原則:
- Router 層只做 HTTP 轉發
- 業務邏輯在 Service 層

@see ADR-031 Omni-Terminal SSE Architecture
@author Claude Code (首席架構師)
@version 1.0.0
@date 2026-03-28 (台北時間)
"""

from datetime import UTC, datetime
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import StreamingResponse

from src.core.logging import get_logger
from src.core.sse import EventType, SSEEvent, get_publisher
from src.models.terminal import (
    TerminalAbortRequest,
    TerminalAbortResponse,
    TerminalIntentRequest,
    TerminalIntentResponse,
    TerminalStatusResponse,
)
from src.core.csrf import CSRFToken  # Phase 20: CSRF Protection
from src.services.terminal_service import TerminalService, get_terminal_service

# Type alias for dependency injection
# Phase 19 首席架構師審查 - 遵循 leWOOOgo 積木化原則
TerminalServiceDep = Annotated[TerminalService, Depends(get_terminal_service)]

router = APIRouter(prefix="/terminal", tags=["Omni-Terminal"])
logger = get_logger("awoooi.terminal.router")


# =============================================================================
# POST /terminal/intent - 提交意圖
# =============================================================================


@router.post(
    "/intent",
    response_model=TerminalIntentResponse,
    summary="提交 Terminal 意圖",
    description="統帥輸入指令或問題，系統建立 Session 並開始處理。返回 session_id 供訂閱 SSE。",
)
async def submit_intent(
    request: TerminalIntentRequest,
    service: TerminalServiceDep,
    _csrf_token: CSRFToken,  # Phase 20: CSRF Protection (驗證用，不需要使用值)
) -> TerminalIntentResponse:
    """
    提交意圖請求

    1. 驗證請求
    2. 建立 Session
    3. 啟動背景處理任務
    4. 返回 session_id 供前端訂閱 SSE
    """
    logger.info(
        "terminal_intent_submit",
        intent=request.intent[:100],
        current_page=request.context.current_page,
    )

    try:
        # 呼叫 Service 處理 (透過 DI 注入)
        session_id = await service.process_intent(request)

        # 建構回應
        return TerminalIntentResponse(
            session_id=session_id,
            stream_url=f"/api/v1/terminal/stream/{session_id}",
            created_at=datetime.now(UTC),
        )

    except Exception as e:
        logger.error(
            "terminal_intent_error",
            error=str(e),
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to process intent: {str(e)}",
        ) from e


# =============================================================================
# GET /terminal/stream/{session_id} - SSE 串流訂閱
# =============================================================================


@router.get(
    "/stream/{session_id}",
    summary="訂閱 Terminal SSE 串流",
    description="Server-Sent Events 串流，接收 AI 思考軌跡、工具呼叫、GenUI 渲染等事件。",
    responses={
        200: {
            "description": "SSE stream",
            "content": {"text/event-stream": {}},
        },
    },
)
async def subscribe_stream(
    session_id: str,
    service: TerminalServiceDep,
    last_event_id: str | None = None,
) -> StreamingResponse:
    """
    訂閱 SSE 串流

    - 使用 Last-Event-ID 實現斷點續傳
    - 自動心跳保持連線
    - 客戶端斷開時自動清理
    """
    logger.info(
        "terminal_stream_subscribe",
        session_id=session_id,
        last_event_id=last_event_id,
    )

    # 驗證 Session 存在 (透過 DI 注入的 service)
    session = await service.get_session(session_id)

    if session is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Session not found: {session_id}",
        )

    # 取得 Publisher
    publisher = await get_publisher()

    # 訂閱 topic
    topic = f"terminal:{session_id}"
    client = await publisher.subscribe(
        topics=[topic],
        metadata={"session_id": session_id},
    )

    async def event_generator():
        """生成 SSE 事件"""
        try:
            async for data in publisher.stream(client):
                yield data
        except Exception as e:
            logger.error(
                "terminal_stream_error",
                session_id=session_id,
                error=str(e),
            )
            # 發送錯誤事件
            error_event = SSEEvent(
                type=EventType.TERMINAL_ERROR,
                data={
                    "session_id": session_id,
                    "error_code": "STREAM_ERROR",
                    "message": str(e),
                    "recoverable": True,
                },
            )
            yield error_event.to_sse_format()

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


# =============================================================================
# POST /terminal/abort/{session_id} - 中斷執行
# =============================================================================


@router.post(
    "/abort/{session_id}",
    response_model=TerminalAbortResponse,
    summary="中斷 Terminal 執行",
    description="中斷正在執行的 AI 分析任務。",
)
async def abort_execution(
    session_id: str,
    service: TerminalServiceDep,
    request: TerminalAbortRequest | None = None,
) -> TerminalAbortResponse:
    """
    中斷執行

    - 取消背景任務
    - 發送中斷事件
    - 更新 Session 狀態
    """
    reason = request.reason if request else None

    logger.info(
        "terminal_abort_request",
        session_id=session_id,
        reason=reason,
    )

    # 透過 DI 注入的 service
    aborted = await service.abort_session(session_id, reason)

    if not aborted:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Session not found or already completed: {session_id}",
        )

    return TerminalAbortResponse(
        session_id=session_id,
        aborted=True,
        message=f"Session aborted{': ' + reason if reason else ''}",
    )


# =============================================================================
# GET /terminal/status/{session_id} - 查詢狀態
# =============================================================================


@router.get(
    "/status/{session_id}",
    response_model=TerminalStatusResponse,
    summary="查詢 Session 狀態",
    description="查詢指定 Session 的當前狀態。",
)
async def get_session_status(
    session_id: str,
    service: TerminalServiceDep,
) -> TerminalStatusResponse:
    """
    查詢 Session 狀態

    用於前端確認:
    - Session 是否存在
    - 當前處理狀態
    - 事件計數 (用於 Last-Event-ID)
    """
    # 透過 DI 注入的 service
    session = await service.get_session(session_id)

    if session is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Session not found: {session_id}",
        )

    return TerminalStatusResponse(
        session_id=session.session_id,
        status=session.status,
        created_at=session.created_at,
        last_event_id=session.last_event_id,
        message_count=session.message_count,
    )
