#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：security.py
模块描述：安全测试 Pydantic 模式定义

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

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


def to_camel(string: str) -> str:
    """Convert snake_case to camelCase"""
    components = string.split('_')
    return components[0] + ''.join(x.title() for x in components[1:])


# ==================== 安全测试配置 ====================

class AccountConfig(BaseModel):
    """测试账号配置"""
    username: str = Field(..., description="用户名")
    password: str = Field(..., description="密码")
    description: str = Field("", description="账号描述")


class AuthConfigDetail(BaseModel):
    """认证配置详情"""
    token_type: str = Field("accessToken", description="Token类型")
    mechanism: str = Field("JWT", description="认证机制")
    login_path: str = Field("/platform/api/auth/login", description="登录路径")
    token_header: str = Field("accessToken", description="Token请求头名称")
    company_number: str = Field("", description="公司编号")
    company_secret: str = Field("", description="公司密钥")
    captcha_path: str = Field("/platform/api/code", description="验证码获取路径")


class RateLimitConfig(BaseModel):
    """限流配置"""
    brute_force_max: int = Field(20, description="暴力破解最大尝试次数")
    rate_limit_max: int = Field(100, description="限流测试最大请求数")
    batch_max: int = Field(50, description="批量测试最大请求数")
    request_interval: float = Field(0.5, description="请求间隔(秒)")


class SecurityConfigCreate(BaseModel):
    """创建安全测试配置"""
    name: str = Field(..., min_length=1, max_length=100, description="配置名称")
    target_url: str = Field(..., description="目标服务器地址")
    server_ip: str = Field("", description="服务器IP")
    verify_ssl: bool = Field(False, description="是否验证SSL证书")
    timeout: int = Field(30, ge=5, le=120, description="请求超时时间(秒)")
    accounts: Dict[str, Any] = Field(default_factory=dict, description="测试账号配置")
    auth_config: Dict[str, Any] = Field(default_factory=dict, description="认证配置")
    rate_limits: Dict[str, Any] = Field(default_factory=dict, description="限流配置")
    api_prefixes: Dict[str, Any] = Field(default_factory=dict, description="API路径前缀")
    is_default: bool = Field(False, description="是否为默认配置")
    description: str = Field("", description="配置描述")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


class SecurityConfigUpdate(BaseModel):
    """更新安全测试配置"""
    name: Optional[str] = Field(None, description="配置名称")
    target_url: Optional[str] = Field(None, description="目标服务器地址")
    server_ip: Optional[str] = Field(None, description="服务器IP")
    verify_ssl: Optional[bool] = Field(None, description="是否验证SSL证书")
    timeout: Optional[int] = Field(None, ge=5, le=120, description="请求超时时间(秒)")
    accounts: Optional[Dict[str, Any]] = Field(None, description="测试账号配置")
    auth_config: Optional[Dict[str, Any]] = Field(None, description="认证配置")
    rate_limits: Optional[Dict[str, Any]] = Field(None, description="限流配置")
    api_prefixes: Optional[Dict[str, Any]] = Field(None, description="API路径前缀")
    is_default: Optional[bool] = Field(None, description="是否为默认配置")
    description: Optional[str] = Field(None, description="配置描述")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


class SecurityConfigResponse(BaseModel):
    """安全测试配置响应"""
    id: str
    name: str
    target_url: str
    server_ip: str = ""
    verify_ssl: bool = False
    timeout: int = 30
    accounts: Dict[str, Any] = {}
    auth_config: Dict[str, Any] = {}
    rate_limits: Dict[str, Any] = {}
    api_prefixes: Dict[str, Any] = {}
    is_default: bool = False
    description: str = ""
    created_at: Optional[str] = None
    updated_at: Optional[str] = None

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


# ==================== 安全测试执行 ====================

class SecurityExecutionCreate(BaseModel):
    """创建安全测试执行"""
    config_id: str = Field(..., description="安全测试配置ID")
    module_ids: List[str] = Field(default_factory=list, description="要执行的模块ID列表(空=全部)")
    case_ids: List[str] = Field(default_factory=list, description="要执行的用例ID列表")
    include_regression: bool = Field(True, description="是否包含历史漏洞回归测试")
    include_redline: bool = Field(True, description="是否包含华为安全红线检查")
    name: str = Field("", description="执行名称")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


class SecurityExecutionResponse(BaseModel):
    """安全测试执行响应"""
    id: str
    name: str = ""
    status: str = "pending"
    total_cases: int = 0
    passed: int = 0
    failed: int = 0
    skipped: int = 0
    duration: float = 0.0
    config_id: str = ""
    start_time: Optional[str] = None
    end_time: Optional[str] = None

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


# ==================== 漏洞结果 ====================

class VulnerabilityResultResponse(BaseModel):
    """漏洞测试结果响应"""
    id: str
    execution_id: str
    case_id: str = ""
    test_id: str = ""
    name: str
    level: str = "info"
    description: str = ""
    request_info: str = ""
    response_info: str = ""
    is_vulnerable: bool = False
    fix_suggestion: str = ""
    duration: float = 0.0
    status: str = "pending"
    error_message: Optional[str] = None
    extra_data: Dict[str, Any] = {}
    created_at: Optional[str] = None

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


# ==================== 知识库 ====================

class HistoricalVuln(BaseModel):
    """历史漏洞条目"""
    vuln_id: str = Field(..., description="漏洞ID")
    title: str = Field(..., description="漏洞标题")
    severity: str = Field(..., description="严重等级")
    vuln_type: str = Field(..., description="漏洞类型")
    source_project: str = Field("", description="来源项目")
    detection_method: str = Field("", description="检测方法")
    regression_note: str = Field("", description="回归验证说明")
    mapped_paths: List[str] = Field(default_factory=list, description="映射路径")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


class HuaweiRedlineCheck(BaseModel):
    """华为安全红线检查项"""
    check_id: str = Field(..., description="检查编号")
    category: str = Field(..., description="检查类别")
    requirement: str = Field(..., description="要求描述")
    severity: str = Field(..., description="严重等级")
    check_method: str = Field("", description="检查方法")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


class KnowledgeBaseResponse(BaseModel):
    """知识库响应"""
    historical_vulns: List[HistoricalVuln] = Field(default_factory=list, description="历史漏洞列表")
    huawei_redlines: List[HuaweiRedlineCheck] = Field(default_factory=list, description="华为红线列表")
    total_vulns: int = Field(0, description="历史漏洞总数")
    total_redlines: int = Field(0, description="红线检查总数")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


# ==================== 账号测试 ====================

class AccountTestRequest(BaseModel):
    """账号连接测试请求"""
    config_id: str = Field(..., description="安全测试配置ID")
    account_key: str = Field(..., description="账号键名(superadmin/admin/user)")

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)


class AccountTestResponse(BaseModel):
    """账号连接测试响应"""
    account_key: str
    success: bool
    token_preview: str = ""
    error_message: str = ""

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
