#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：stats.py
模块描述：统计分析 API 路由

作者：czj
创建日期：2026-07-09
最后修改：2026-07-09
"""

import logging
from typing import Optional
from datetime import datetime, timedelta

from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, and_, case

from app.database import get_db
from app.models.execution import Execution
from app.models.case_result import CaseResult
from app.models.test_case import TestCase
from app.models.module import Module

logger = logging.getLogger(__name__)

router = APIRouter()


@router.get("/overview", response_model=dict)
async def get_overview_stats(
    days: int = Query(30, ge=1, le=365, description="统计天数"),
    db: AsyncSession = Depends(get_db),
):
    """
    获取总览统计数据

    返回指定天数内的执行统计、用例统计、通过率等。

    Args:
        days (int): 统计天数
        db (AsyncSession): 数据库会话

    Returns:
        dict: 总览统计数据
    """
    start_date = datetime.now() - timedelta(days=days)

    # 执行统计
    exec_count_query = select(func.count(Execution.id)).where(
        Execution.created_at >= start_date
    )
    result = await db.execute(exec_count_query)
    total_executions = result.scalar() or 0

    # 用例执行结果统计
    result_count_query = select(
        func.count(CaseResult.id).label("total"),
        func.sum(case((CaseResult.status == "passed", 1), else_=0)).label("passed"),
        func.sum(case((CaseResult.status == "failed", 1), else_=0)).label("failed"),
        func.sum(case((CaseResult.status == "skipped", 1), else_=0)).label("skipped"),
    ).join(Execution).where(Execution.created_at >= start_date)
    result = await db.execute(result_count_query)
    row = result.one()

    total_case_runs = row.total or 0
    passed = row.passed or 0
    failed = row.failed or 0
    skipped = row.skipped or 0

    pass_rate = round(passed / total_case_runs * 100, 1) if total_case_runs > 0 else 0.0

    # 用例总数
    case_count_query = select(func.count(TestCase.id))
    result = await db.execute(case_count_query)
    total_cases = result.scalar() or 0

    # 模块总数
    module_count_query = select(func.count(Module.id))
    result = await db.execute(module_count_query)
    total_modules = result.scalar() or 0

    # 最近执行
    recent_query = (
        select(Execution)
        .order_by(Execution.created_at.desc())
        .limit(5)
    )
    result = await db.execute(recent_query)
    recent_executions = [
        {
            "id": e.id,
            "name": e.name,
            "status": e.status,
            "pass_rate": e.pass_rate,
            "duration": e.duration,
            "trigger_by": e.trigger_by,
            "created_at": e.created_at.isoformat() if e.created_at else None,
        }
        for e in result.scalars().all()
    ]

    return {
        "period_days": days,
        "executions": {
            "total": total_executions,
        },
        "case_runs": {
            "total": total_case_runs,
            "passed": passed,
            "failed": failed,
            "skipped": skipped,
            "pass_rate": pass_rate,
        },
        "cases": {
            "total": total_cases,
        },
        "modules": {
            "total": total_modules,
        },
        "recent_executions": recent_executions,
    }


@router.get("/trend", response_model=dict)
async def get_trend_stats(
    days: int = Query(30, ge=7, le=365, description="统计天数"),
    db: AsyncSession = Depends(get_db),
):
    """
    获取趋势统计数据

    返回每日执行次数和通过率趋势。

    Args:
        days (int): 统计天数
        db (AsyncSession): 数据库会话

    Returns:
        dict: 趋势统计数据
    """
    start_date = datetime.now() - timedelta(days=days)

    # 按日期分组统计执行次数
    # SQLite 使用 date() 函数提取日期
    exec_trend_query = (
        select(
            func.date(Execution.created_at).label("date"),
            func.count(Execution.id).label("count"),
            func.avg(Execution.pass_rate).label("avg_pass_rate"),
        )
        .where(Execution.created_at >= start_date)
        .group_by(func.date(Execution.created_at))
        .order_by(func.date(Execution.created_at))
    )
    result = await db.execute(exec_trend_query)
    rows = result.all()

    trend_data = [
        {
            "date": str(row.date),
            "executions": row.count,
            "pass_rate": round(row.avg_pass_rate or 0, 1),
        }
        for row in rows
    ]

    # 填充缺失的日期
    date_set = {str(row.date) for row in rows}
    current_date = start_date.date()
    end_date = datetime.now().date()

    filled_trend = []
    while current_date <= end_date:
        date_str = str(current_date)
        if date_str in date_set:
            filled_trend.append(next(t for t in trend_data if t["date"] == date_str))
        else:
            filled_trend.append({
                "date": date_str,
                "executions": 0,
                "pass_rate": 0.0,
            })
        current_date += timedelta(days=1)

    return {
        "period_days": days,
        "trend": filled_trend,
    }


@router.get("/modules", response_model=dict)
async def get_module_stats(
    db: AsyncSession = Depends(get_db),
):
    """
    获取模块统计数据

    返回各模块的用例数量和执行情况。

    Args:
        db (AsyncSession): 数据库会话

    Returns:
        dict: 模块统计数据
    """
    # 查询模块及其用例数量
    query = (
        select(
            Module.id,
            Module.name,
            Module.icon,
            func.count(TestCase.id).label("case_count"),
        )
        .outerjoin(TestCase, Module.id == TestCase.module_id)
        .group_by(Module.id)
        .order_by(Module.order)
    )
    result = await db.execute(query)
    rows = result.all()

    modules_stats = []
    for row in rows:
        modules_stats.append({
            "id": row.id,
            "name": row.name,
            "icon": row.icon,
            "case_count": row.case_count,
        })

    return {
        "modules": modules_stats,
    }


@router.get("/module/{module_id}", response_model=dict)
async def get_module_detail_stats(
    module_id: str,
    days: int = Query(30, ge=1, le=365, description="统计天数"),
    db: AsyncSession = Depends(get_db),
):
    """
    获取单个模块的详细统计

    Args:
        module_id (str): 模块ID
        days (int): 统计天数
        db (AsyncSession): 数据库会话

    Returns:
        dict: 模块详细统计
    """
    start_date = datetime.now() - timedelta(days=days)

    # 获取模块信息
    module_query = select(Module).where(Module.id == module_id)
    result = await db.execute(module_query)
    module = result.scalar_one_or_none()

    if not module:
        return {"error": "模块不存在"}

    # 统计用例数量
    case_count_query = select(func.count(TestCase.id)).where(
        TestCase.module_id == module_id
    )
    result = await db.execute(case_count_query)
    total_cases = result.scalar() or 0

    # 统计执行情况
    # 通过用例找执行结果
    result_query = (
        select(
            func.count(CaseResult.id).label("total"),
            func.sum(case((CaseResult.status == "passed", 1), else_=0)).label("passed"),
            func.sum(case((CaseResult.status == "failed", 1), else_=0)).label("failed"),
        )
        .join(TestCase, CaseResult.case_id == TestCase.id)
        .where(
            TestCase.module_id == module_id,
            CaseResult.created_at >= start_date,
        )
    )
    result = await db.execute(result_query)
    row = result.one()

    total_runs = row.total or 0
    passed = row.passed or 0
    failed = row.failed or 0

    pass_rate = round(passed / total_runs * 100, 1) if total_runs > 0 else 0.0

    return {
        "module": {
            "id": module.id,
            "name": module.name,
            "description": module.description,
        },
        "period_days": days,
        "total_cases": total_cases,
        "execution_stats": {
            "total_runs": total_runs,
            "passed": passed,
            "failed": failed,
            "pass_rate": pass_rate,
        },
    }


@router.get("/priority", response_model=dict)
async def get_priority_stats(
    db: AsyncSession = Depends(get_db),
):
    """
    获取用例优先级分布

    Args:
        db (AsyncSession): 数据库会话

    Returns:
        dict: 优先级统计
    """
    query = (
        select(
            TestCase.priority,
            func.count(TestCase.id).label("count"),
        )
        .group_by(TestCase.priority)
    )
    result = await db.execute(query)
    rows = result.all()

    priority_map = {
        "high": "高",
        "medium": "中",
        "low": "低",
    }

    stats = {}
    for row in rows:
        key = row.priority or "medium"
        stats[key] = {
            "label": priority_map.get(key, key),
            "count": row.count,
        }

    # 确保所有优先级都有数据
    for key in ["high", "medium", "low"]:
        if key not in stats:
            stats[key] = {
                "label": priority_map[key],
                "count": 0,
            }

    return {
        "priority": stats,
    }


@router.get("/status", response_model=dict)
async def get_status_stats(
    db: AsyncSession = Depends(get_db),
):
    """
    获取用例状态分布

    Args:
        db (AsyncSession): 数据库会话

    Returns:
        dict: 状态统计
    """
    query = (
        select(
            TestCase.status,
            func.count(TestCase.id).label("count"),
        )
        .group_by(TestCase.status)
    )
    result = await db.execute(query)
    rows = result.all()

    status_map = {
        "active": "启用",
        "disabled": "禁用",
    }

    stats = {}
    for row in rows:
        key = row.status or "active"
        stats[key] = {
            "label": status_map.get(key, key),
            "count": row.count,
        }

    # 确保所有状态都有数据
    for key in ["active", "disabled"]:
        if key not in stats:
            stats[key] = {
                "label": status_map[key],
                "count": 0,
            }

    return {
        "status": stats,
    }
