#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：execution.py
模块描述：执行记录数据库模型定义

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

from datetime import datetime
from typing import Optional
from sqlalchemy import String, Integer, Float, JSON, DateTime, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base


class Execution(Base):
    """
    执行记录数据库模型

    记录每次测试执行的整体信息，包括执行状态、统计数据等。

    Attributes:
        id (str): 执行记录唯一标识
        name (str): 执行名称
        trigger_type (str): 触发类型 (manual/scheduled)
        trigger_by (str): 触发人/任务名
        total_cases (int): 总用例数
        passed (int): 通过数
        failed (int): 失败数
        skipped (int): 跳过数
        pass_rate (float): 通过率
        duration (float): 总耗时（秒）
        status (str): 状态 (running/completed/cancelled/failed)
        start_time (datetime): 开始时间
        end_time (datetime): 结束时间
        environment (str): 执行环境
        config (dict): 执行配置

    Example:
        >>> execution = Execution(
        ...     id="exec_abc123",
        ...     name="全量测试-20260709",
        ...     trigger_type="manual",
        ...     trigger_by="czj"
        ... )
    """

    __tablename__ = "executions"

    id: Mapped[str] = mapped_column(String(64), primary_key=True, comment="执行ID")
    name: Mapped[str] = mapped_column(String(200), default="", comment="执行名称")
    trigger_type: Mapped[str] = mapped_column(
        String(20),
        default="manual",
        comment="触发类型: manual/scheduled"
    )
    trigger_by: Mapped[str] = mapped_column(String(100), default="", comment="触发人/任务名")
    total_cases: Mapped[int] = mapped_column(Integer, default=0, comment="总用例数")
    passed: Mapped[int] = mapped_column(Integer, default=0, comment="通过数")
    failed: Mapped[int] = mapped_column(Integer, default=0, comment="失败数")
    skipped: Mapped[int] = mapped_column(Integer, default=0, comment="跳过数")
    pass_rate: Mapped[float] = mapped_column(Float, default=0.0, comment="通过率")
    duration: Mapped[float] = mapped_column(Float, default=0.0, comment="总耗时(秒)")
    status: Mapped[str] = mapped_column(
        String(20),
        default="pending",
        comment="状态: pending/running/completed/cancelled/failed"
    )
    error_message: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True,
        comment="错误信息（执行失败时记录）"
    )
    start_time: Mapped[Optional[datetime]] = mapped_column(
        DateTime,
        nullable=True,
        comment="开始时间"
    )
    end_time: Mapped[Optional[datetime]] = mapped_column(
        DateTime,
        nullable=True,
        comment="结束时间"
    )
    environment: Mapped[str] = mapped_column(String(50), default="default", comment="执行环境")
    config: Mapped[dict] = mapped_column(JSON, default=dict, comment="执行配置")
    case_type: Mapped[str] = mapped_column(
        String(20),
        default="ui",
        comment="用例类型: ui/api/security/deploy（用于按类型筛选执行记录）"
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.utcnow,
        comment="创建时间"
    )

    # 关联用例结果（一对多）
    case_results: Mapped[list["CaseResult"]] = relationship(
        "CaseResult",
        back_populates="execution",
        cascade="all, delete-orphan"
    )

    # 关联漏洞测试结果（一对多）
    vulnerability_results: Mapped[list["VulnerabilityResult"]] = relationship(
        "VulnerabilityResult",
        back_populates="execution",
        cascade="all, delete-orphan"
    )

    def __repr__(self) -> str:
        """字符串表示"""
        return f"<Execution(id={self.id}, status={self.status}, pass_rate={self.pass_rate}%)>"

    def to_dict(self) -> dict:
        """
        转换为字典

        Returns:
            dict: 执行记录数据字典
        """
        return {
            "id": self.id,
            "name": self.name,
            "trigger_type": self.trigger_type,
            "trigger_by": self.trigger_by,
            "total_cases": self.total_cases,
            "passed": self.passed,
            "failed": self.failed,
            "skipped": self.skipped,
            "pass_rate": self.pass_rate,
            "duration": self.duration,
            "status": self.status,
            "error_message": self.error_message,
            "start_time": self.start_time.isoformat() if self.start_time else None,
            "end_time": self.end_time.isoformat() if self.end_time else None,
            "environment": self.environment,
            "config": self.config or {},
            "case_type": self.case_type,
            "created_at": self.created_at.isoformat() if self.created_at else None,
        }

    def calculate_pass_rate(self) -> float:
        """
        计算通过率

        Returns:
            float: 通过率百分比
        """
        if self.total_cases == 0:
            return 0.0
        return round((self.passed / self.total_cases) * 100, 2)
