#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：api_test.py
模块描述：接口测试 Pydantic 模式定义 — 断言规则、请求配置、执行结果

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

from datetime import datetime
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field


# ==================== 断言规则 ====================

class AssertionRule(BaseModel):
    """
    断言规则

    支持三种断言类型：
    - status_code: HTTP 状态码比较
    - body_field: 响应体 JSONPath 字段检查
    - response_time: 响应时间比较（ms）
    - header: 响应头检查

    Attributes:
        type (str): 断言类型
        operator (str): 运算符 (equals/not_equals/contains/regex/greater_than/less_than)
        value (Any): 期望值
        path (Optional[str]): JSONPath（body_field 类型必填）
    """
    type: str = Field(..., description="断言类型: status_code/body_field/response_time/header")
    operator: str = Field("equals", description="运算符: equals/not_equals/contains/regex/greater_than/less_than")
    value: Any = Field(..., description="期望值")
    path: Optional[str] = Field(None, description="JSONPath（body_field 类型必填，如 $.code）")


# ==================== 请求配置 ====================

class ApiRequestConfig(BaseModel):
    """
    接口测试用例的请求配置（存储在 test_cases.steps 字段中）

    Attributes:
        method (str): HTTP 方法
        url (str): 接口路径（相对路径，如 /meetingV3/api/message/book）
        headers (dict): 自定义请求头
        body (Any): 请求体（支持 dict/list/str）
        auth_required (bool): 是否需要登录 Token
        sign_request (bool): 是否需要签名
        account_key (str): 账号 key
        assertions (list): 断言规则列表
        description (str): 用例描述/预期说明
    """
    method: str = Field("GET", description="HTTP 方法")
    url: str = Field(..., description="接口路径（相对路径）")
    headers: Dict[str, str] = Field(default_factory=dict, description="自定义请求头")
    body: Any = Field(None, description="请求体")
    auth_required: bool = Field(True, description="是否需要登录 Token")
    sign_request: bool = Field(False, description="是否需要签名")
    account_key: str = Field("superadmin", description="账号 key")
    assertions: List[AssertionRule] = Field(default_factory=list, description="断言规则列表")
    description: str = Field("", description="用例描述/预期说明")


# ==================== 执行相关 ====================

class ApiAssertionResult(BaseModel):
    """
    单条断言执行结果

    Attributes:
        type (str): 断言类型
        operator (str): 运算符
        expected (Any): 期望值
        actual (Any): 实际值
        passed (bool): 是否通过
        message (str): 描述信息
    """
    type: str = Field("", description="断言类型")
    operator: str = Field("", description="运算符")
    expected: Any = Field(None, description="期望值")
    actual: Any = Field(None, description="实际值")
    passed: bool = Field(False, description="是否通过")
    message: str = Field("", description="描述信息")


class ApiStepResult(BaseModel):
    """
    单次 API 请求执行结果（存储在 case_results.steps_result 中）

    Attributes:
        order (int): 步骤序号
        name (str): 步骤名称
        method (str): 请求方法
        url (str): 请求完整 URL
        status_code (int): HTTP 状态码
        response_time (float): 响应时间（ms）
        request_headers (dict): 请求头
        request_body (Any): 请求体
        response_headers (dict): 响应头
        response_body (str): 响应体文本
        assertions (list): 断言执行结果
        passed (bool): 是否通过
        error (str): 错误信息
    """
    order: int = Field(0, description="步骤序号")
    name: str = Field("", description="步骤名称")
    method: str = Field("", description="请求方法")
    url: str = Field("", description="请求完整 URL")
    status_code: int = Field(0, description="HTTP 状态码")
    response_time: float = Field(0.0, description="响应时间（ms）")
    request_headers: Dict[str, str] = Field(default_factory=dict, description="请求头")
    request_body: Any = Field(None, description="请求体")
    response_headers: Dict[str, str] = Field(default_factory=dict, description="响应头")
    response_body: str = Field("", description="响应体文本")
    assertions: List[ApiAssertionResult] = Field(default_factory=list, description="断言执行结果")
    passed: bool = Field(False, description="是否通过")
    error: str = Field("", description="错误信息")


# ==================== API 请求/响应 ====================

class ApiTestExecuteRequest(BaseModel):
    """
    执行接口测试请求

    Attributes:
        case_ids (list): 用例 ID 列表
        config_id (Optional[str]): 安全测试配置 ID（复用登录配置）
        target_url (Optional[str]): 目标服务器 base URL
        name (Optional[str]): 执行名称（可选，留空自动生成）
    """
    case_ids: List[str] = Field(..., description="用例 ID 列表", min_length=1)
    config_id: Optional[str] = Field(None, description="安全测试配置 ID，复用登录配置")
    target_url: Optional[str] = Field(None, description="目标服务器 base URL，如 https://192.168.5.44")
    name: Optional[str] = Field(None, description="执行名称，留空自动生成")


class ApiTestExecuteResponse(BaseModel):
    """
    执行接口测试响应

    Attributes:
        execution_id (str): 执行记录 ID
        status (str): 状态
        message (str): 消息
    """
    execution_id: str = Field("", description="执行记录 ID")
    status: str = Field("", description="状态")
    message: str = Field("", description="消息")


class ApiTestResultItem(BaseModel):
    """
    接口测试结果项（单条用例）

    Attributes:
        case_id (str): 用例 ID
        case_name (str): 用例名称
        status (str): 状态 (passed/failed/skipped)
        duration (float): 耗时（秒）
        step_result (ApiStepResult): 执行详情
        error (str): 错误信息
    """
    case_id: str = Field("", description="用例 ID")
    case_name: str = Field("", description="用例名称")
    status: str = Field("", description="状态: passed/failed/skipped")
    duration: float = Field(0.0, description="耗时（秒）")
    step_result: Optional[ApiStepResult] = Field(None, description="执行详情")
    error: str = Field("", description="错误信息")


class ApiTestExecutionSummary(BaseModel):
    """
    接口测试执行摘要

    Attributes:
        execution_id (str): 执行记录 ID
        name (str): 执行名称
        status (str): 状态
        total (int): 总用例数
        passed (int): 通过数
        failed (int): 失败数
        start_time (str): 开始时间
        end_time (str): 结束时间
        duration (float): 总耗时
        results (list): 详细结果列表
    """
    execution_id: str = Field("", description="执行记录 ID")
    name: str = Field("", description="执行名称")
    status: str = Field("", description="状态")
    total: int = Field(0, description="总用例数")
    passed: int = Field(0, description="通过数")
    failed: int = Field(0, description="失败数")
    start_time: Optional[str] = Field(None, description="开始时间")
    end_time: Optional[str] = Field(None, description="结束时间")
    duration: float = Field(0.0, description="总耗时（秒）")
    results: List[ApiTestResultItem] = Field(default_factory=list, description="详细结果列表")