#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：main.py
模块描述：FastAPI 应用入口，负责启动 Web 服务和注册路由

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

import asyncio
import logging
import os
import sys
from contextlib import asynccontextmanager
from pathlib import Path

# Windows 平台设置 ProactorEventLoop 以支持子进程操作
if sys.platform == 'win32':
    asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse

from app.config import settings
from app.database import init_db
from app.routers import modules, cases, executions, recorder, stats, reports, cleanup, batch, dependencies, security

# 配置日志
logging.basicConfig(
    level=logging.INFO if not settings.DEBUG else logging.DEBUG,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    应用生命周期管理

    在应用启动时初始化数据库，在关闭时清理资源。

    Yields:
        None
    """
    # 启动时
    logger.info(f"正在启动 {settings.APP_NAME} v{settings.APP_VERSION}")

    # 确保必要的目录存在
    Path(settings.SCREENSHOT_DIR).mkdir(parents=True, exist_ok=True)
    Path(settings.REPORT_DIR).mkdir(parents=True, exist_ok=True)
    logger.info("目录初始化完成")

    await init_db()
    logger.info("数据库初始化完成")

    yield

    # 关闭时
    logger.info("应用正在关闭...")


# 创建 FastAPI 应用实例
app = FastAPI(
    title=settings.APP_NAME,
    description="Web 可视化自动化测试平台 API - 支持用例录制、执行、结果分析",
    version=settings.APP_VERSION,
    lifespan=lifespan,
    docs_url="/docs",
    redoc_url="/redoc",
)

# 配置 CORS 中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


# ==================== 注册路由 ====================

app.include_router(
    modules.router,
    prefix="/api/modules",
    tags=["模块管理"]
)

app.include_router(
    cases.router,
    prefix="/api/cases",
    tags=["用例管理"]
)

app.include_router(
    executions.router,
    prefix="/api/executions",
    tags=["执行管理"]
)

app.include_router(
    recorder.router,
    prefix="/api/recorder",
    tags=["用例录制"]
)

app.include_router(
    stats.router,
    prefix="/api/stats",
    tags=["统计分析"]
)

app.include_router(
    reports.router,
    prefix="/api/reports",
    tags=["报告管理"]
)

app.include_router(
    cleanup.router,
    prefix="/api/cleanup",
    tags=["数据清理"]
)

app.include_router(
    batch.router,
    prefix="/api/batch",
    tags=["批量操作"]
)

app.include_router(
    dependencies.router,
    prefix="/api",
    tags=["依赖管理"]
)

app.include_router(
    security.router,
    prefix="/api/security",
    tags=["安全测试"]
)


# ==================== 根路径 ====================

@app.get("/", tags=["健康检查"])
async def root():
    """
    根路径健康检查

    返回服务状态信息，用于确认服务正常运行。

    Returns:
        dict: 服务状态信息
    """
    return {
        "status": "ok",
        "message": f"{settings.APP_NAME} API 服务运行中",
        "version": settings.APP_VERSION
    }


@app.get("/health", tags=["健康检查"])
async def health_check():
    """
    详细健康检查

    返回服务和数据库连接状态。

    Returns:
        dict: 详细健康状态
    """
    return {
        "status": "healthy",
        "service": settings.APP_NAME,
        "version": settings.APP_VERSION,
        "debug": settings.DEBUG
    }


# ==================== 文件服务 ====================

@app.get("/api/files/{file_path:path}", tags=["文件服务"])
async def serve_file(file_path: str):
    """
    提供截图等静态文件访问

    支持路径格式：自定义相对路径

    Args:
        file_path (str): 文件相对路径

    Returns:
        FileResponse: 文件响应
    """
    # 支持多种可能的路径
    possible_paths = [
        Path(file_path),                      # 直接路径
        Path("data") / file_path,             # data/ 前缀
        Path(settings.SCREENSHOT_DIR) / Path(file_path).name,  # 截图目录
    ]

    for p in possible_paths:
        resolved = p.resolve()
        if resolved.exists() and resolved.is_file():
            return FileResponse(str(resolved))

    raise HTTPException(
        status_code=404,
        detail=f"文件不存在: {file_path}"
    )