#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：performance_output.py
模块描述：性能测试任务输出查询 API 路由

提供从响应体捕获的字段值查询接口，供前端展示和 REF 引用验证。

作者：czj
创建日期：2026-08-13
"""

import logging
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select, func, desc
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.models.performance_output import PerformanceTaskOutput
from app.schemas.performance_output import (
    PerformanceTaskOutputResponse,
    PerformanceTaskOutputListResponse,
)

logger = logging.getLogger(__name__)

router = APIRouter()


@router.get("/outputs", response_model=PerformanceTaskOutputListResponse)
async def list_outputs(
    task_id: Optional[str] = Query(None, description="按任务ID过滤"),
    key: Optional[str] = Query(None, description="按键名过滤"),
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: AsyncSession = Depends(get_db),
):
    """
    获取任务输出列表（分页）

    支持按 task_id 和 key 过滤，用于 REF 引用验证和前端展示。

    注意：value 列可能存数千个捕获值（数 MB JSON），ORDER BY 若带整行
    会触发 MySQL filesort 爆 sort buffer（Out of sort memory）。
    故采用两段式：先只按 id 轻量排序分页，再按 id 回查整行。
    """
    conditions = []
    if task_id:
        conditions.append(PerformanceTaskOutput.task_id == task_id)
    if key:
        conditions.append(PerformanceTaskOutput.key == key)

    count_query = select(func.count()).select_from(PerformanceTaskOutput)
    if conditions:
        count_query = count_query.where(*conditions)
    total = (await db.execute(count_query)).scalar() or 0

    # 第一段：轻量排序（只取 id，value 大列不进 sort buffer）
    id_query = select(PerformanceTaskOutput.id)
    if conditions:
        id_query = id_query.where(*conditions)
    id_query = (
        id_query.order_by(desc(PerformanceTaskOutput.created_at))
        .offset((page - 1) * page_size)
        .limit(page_size)
    )
    ids = [row[0] for row in (await db.execute(id_query)).all()]

    # 第二段：按 id 回查整行，并按第一段顺序还原分页
    items: list = []
    if ids:
        rows = await db.execute(
            select(PerformanceTaskOutput).where(PerformanceTaskOutput.id.in_(ids))
        )
        by_id = {o.id: o for o in rows.scalars().all()}
        items = [by_id[i] for i in ids if i in by_id]

    return PerformanceTaskOutputListResponse(
        total=total,
        items=[PerformanceTaskOutputResponse(**item.to_dict()) for item in items],
    )


@router.get("/outputs/{output_id}", response_model=PerformanceTaskOutputResponse)
async def get_output(
    output_id: int,
    db: AsyncSession = Depends(get_db),
):
    """获取单个任务输出详情"""
    output = await db.get(PerformanceTaskOutput, output_id)
    if not output:
        raise HTTPException(status_code=404, detail="输出记录不存在")
    return PerformanceTaskOutputResponse(**output.to_dict())


@router.get("/tasks/{task_id}/outputs", response_model=PerformanceTaskOutputListResponse)
async def get_task_outputs(
    task_id: str,
    key: Optional[str] = Query(None, description="按键名过滤"),
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: AsyncSession = Depends(get_db),
):
    """
    获取某个任务的所有输出

    便捷接口，直接按 task_id 查询，可指定 key 过滤特定字段。
    同 list_outputs：两段式查询避免大 value 列参与 ORDER BY。
    """
    conditions = [PerformanceTaskOutput.task_id == task_id]
    if key:
        conditions.append(PerformanceTaskOutput.key == key)

    count_query = (
        select(func.count())
        .select_from(PerformanceTaskOutput)
        .where(*conditions)
    )
    total = (await db.execute(count_query)).scalar() or 0

    # 第一段：轻量排序（只取 id）
    id_query = (
        select(PerformanceTaskOutput.id)
        .where(*conditions)
        .order_by(PerformanceTaskOutput.created_at.asc())
        .offset((page - 1) * page_size)
        .limit(page_size)
    )
    ids = [row[0] for row in (await db.execute(id_query)).all()]

    # 第二段：按 id 回查整行，按第一段顺序还原分页
    items: list = []
    if ids:
        rows = await db.execute(
            select(PerformanceTaskOutput).where(PerformanceTaskOutput.id.in_(ids))
        )
        by_id = {o.id: o for o in rows.scalars().all()}
        items = [by_id[i] for i in ids if i in by_id]

    return PerformanceTaskOutputListResponse(
        total=total,
        items=[PerformanceTaskOutputResponse(**item.to_dict()) for item in items],
    )