# -*- coding: utf-8 -*-
"""执行与队列 API

提供 8 个端点：
- POST /api/execution/run          — 直接执行任务
- GET  /api/execution/queue        — 获取当前队列（按 site_id 过滤）
- POST /api/execution/queue        — 添加到队列
- PUT  /api/execution/queue/reorder — 重排队列
- DELETE /api/execution/queue/{id} — 删除队列任务
- POST /api/execution/{id}/cancel  — 取消执行中的任务
- GET  /api/execution/history      — 执行历史（按 site_id 过滤）
- GET  /api/execution/{id}/logs    — 获取历史日志

所有端点需要 JWT 认证，site_id 从 JWT 提取。
"""

from __future__ import annotations

import asyncio
import json
import logging
import uuid

from fastapi import APIRouter, Depends, HTTPException, Query, status

from app.auth.dependencies import CurrentUser, get_current_user
from app.database import get_connection
from app.schemas.execution import (
    ExecutionHistoryItem,
    ExecutionLogsResponse,
    ExecutionRunResponse,
    QueueTaskResponse,
    ReorderRequest,
)
from app.schemas.tasks import TaskConfigSchema
from app.services.task_executor import task_executor
from app.services.task_queue import task_queue

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/execution", tags=["任务执行"])


# ── POST /api/execution/run — 直接执行任务 ────────────────────

@router.post("/run", response_model=ExecutionRunResponse)
async def run_task(
    config: TaskConfigSchema,
    user: CurrentUser = Depends(get_current_user),
) -> ExecutionRunResponse:
    """直接执行任务（不经过队列）。

    从 JWT 注入 store_id，创建 execution_id 后异步启动子进程。
    """
    config = config.model_copy(update={"store_id": user.site_id})
    execution_id = str(uuid.uuid4())

    # 异步启动执行，不阻塞响应
    asyncio.create_task(
        task_executor.execute(
            config=config,
            execution_id=execution_id,
            site_id=user.site_id,
        )
    )

    return ExecutionRunResponse(
        execution_id=execution_id,
        message="任务已提交执行",
    )


# ── GET /api/execution/queue — 获取当前队列 ───────────────────

@router.get("/queue", response_model=list[QueueTaskResponse])
async def get_queue(
    user: CurrentUser = Depends(get_current_user),
) -> list[QueueTaskResponse]:
    """获取当前门店的待执行队列。"""
    tasks = task_queue.list_pending(user.site_id)
    return [
        QueueTaskResponse(
            id=t.id,
            site_id=t.site_id,
            config=t.config,
            status=t.status,
            position=t.position,
            created_at=t.created_at,
            started_at=t.started_at,
            finished_at=t.finished_at,
            exit_code=t.exit_code,
            error_message=t.error_message,
        )
        for t in tasks
    ]


# ── POST /api/execution/queue — 添加到队列 ───────────────────

@router.post("/queue", response_model=QueueTaskResponse, status_code=status.HTTP_201_CREATED)
async def enqueue_task(
    config: TaskConfigSchema,
    user: CurrentUser = Depends(get_current_user),
) -> QueueTaskResponse:
    """将任务配置添加到执行队列。"""
    config = config.model_copy(update={"store_id": user.site_id})
    task_id = task_queue.enqueue(config, user.site_id)

    # 查询刚创建的任务返回完整信息
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT id, site_id, config, status, position,
                       created_at, started_at, finished_at,
                       exit_code, error_message
                FROM task_queue WHERE id = %s
                """,
                (task_id,),
            )
            row = cur.fetchone()
        conn.commit()
    finally:
        conn.close()

    if row is None:
        raise HTTPException(status_code=500, detail="入队后查询失败")

    config_data = row[2] if isinstance(row[2], dict) else json.loads(row[2])
    return QueueTaskResponse(
        id=str(row[0]),
        site_id=row[1],
        config=config_data,
        status=row[3],
        position=row[4],
        created_at=row[5],
        started_at=row[6],
        finished_at=row[7],
        exit_code=row[8],
        error_message=row[9],
    )


# ── PUT /api/execution/queue/reorder — 重排队列 ──────────────

@router.put("/queue/reorder")
async def reorder_queue(
    body: ReorderRequest,
    user: CurrentUser = Depends(get_current_user),
) -> dict:
    """调整队列中任务的执行顺序。"""
    task_queue.reorder(body.task_id, body.new_position, user.site_id)
    return {"message": "队列已重排"}


# ── DELETE /api/execution/queue/{id} — 删除队列任务 ──────────

@router.delete("/queue/{task_id}")
async def delete_queue_task(
    task_id: str,
    user: CurrentUser = Depends(get_current_user),
) -> dict:
    """从队列中删除待执行任务。仅允许删除 pending 状态的任务。"""
    deleted = task_queue.delete(task_id, user.site_id)
    if not deleted:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="任务不存在或非待执行状态，无法删除",
        )
    return {"message": "任务已从队列中删除"}


# ── POST /api/execution/{id}/cancel — 取消执行 ──────────────

@router.post("/{execution_id}/cancel")
async def cancel_execution(
    execution_id: str,
    user: CurrentUser = Depends(get_current_user),
) -> dict:
    """取消正在执行的任务。"""
    cancelled = await task_executor.cancel(execution_id)
    if not cancelled:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="执行任务不存在或已完成",
        )
    return {"message": "已发送取消信号"}


# ── GET /api/execution/history — 执行历史 ────────────────────

@router.get("/history", response_model=list[ExecutionHistoryItem])
async def get_execution_history(
    limit: int = Query(default=50, ge=1, le=200),
    user: CurrentUser = Depends(get_current_user),
) -> list[ExecutionHistoryItem]:
    """获取执行历史记录，按 started_at 降序排列。"""
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT id, site_id, task_codes, status, started_at,
                       finished_at, exit_code, duration_ms, command, summary,
                       schedule_id
                FROM task_execution_log
                WHERE site_id = %s
                ORDER BY started_at DESC
                LIMIT %s
                """,
                (user.site_id, limit),
            )
            rows = cur.fetchall()
        conn.commit()
    finally:
        conn.close()

    return [
        ExecutionHistoryItem(
            id=str(row[0]),
            site_id=row[1],
            task_codes=row[2] or [],
            status=row[3],
            started_at=row[4],
            finished_at=row[5],
            exit_code=row[6],
            duration_ms=row[7],
            command=row[8],
            summary=row[9],
            schedule_id=str(row[10]) if row[10] else None,
        )
        for row in rows
    ]


# ── GET /api/execution/{id}/logs — 获取历史日志 ──────────────

@router.get("/{execution_id}/logs", response_model=ExecutionLogsResponse)
async def get_execution_logs(
    execution_id: str,
    user: CurrentUser = Depends(get_current_user),
) -> ExecutionLogsResponse:
    """获取指定执行的完整日志。

    优先从内存缓冲区读取（执行中），否则从数据库读取（已完成）。
    """
    # 先尝试内存缓冲区（执行中的任务）
    if task_executor.is_running(execution_id):
        lines = task_executor.get_logs(execution_id)
        return ExecutionLogsResponse(
            execution_id=execution_id,
            output_log="\n".join(lines) if lines else None,
        )

    # 从数据库读取已完成任务的日志
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT output_log, error_log
                FROM task_execution_log
                WHERE id = %s AND site_id = %s
                """,
                (execution_id, user.site_id),
            )
            row = cur.fetchone()
        conn.commit()
    finally:
        conn.close()

    if row is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="执行记录不存在",
        )

    return ExecutionLogsResponse(
        execution_id=execution_id,
        output_log=row[0],
        error_log=row[1],
    )
