#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：test_case.py
模块描述：测试用例数据库模型定义

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

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

from app.database import Base


class TestCase(Base):
    """
    测试用例数据库模型

    存储测试用例信息，包括测试步骤定义和执行配置。

    Attributes:
        id (str): 用例唯一标识
        module_id (str): 所属模块ID
        name (str): 用例名称，最大长度200字符
        description (str): 用例描述
        status (str): 状态 (active/disabled)
        priority (str): 优先级 (high/medium/low)
        tags (list): 标签列表
        steps (list): 测试步骤定义，JSON 格式
        config (dict): 执行配置，JSON 格式
        created_at (datetime): 创建时间
        updated_at (datetime): 更新时间

    Example:
        >>> test_case = TestCase(
        ...     id="case_abc123",
        ...     module_id="module_xyz",
        ...     name="正常登录测试",
        ...     steps=[
        ...         {"order": 1, "action": "navigate", "params": {"url": "/login"}},
        ...         {"order": 2, "action": "fill", "params": {"selector": "#username"}}
        ...     ]
        ... )
    """

    __tablename__ = "test_cases"

    id: Mapped[str] = mapped_column(String(64), primary_key=True, comment="用例ID")
    module_id: Mapped[str] = mapped_column(
        String(64),
        ForeignKey("modules.id", ondelete="CASCADE"),
        nullable=False,
        comment="所属模块ID"
    )
    name: Mapped[str] = mapped_column(String(200), nullable=False, comment="用例名称")
    description: Mapped[str] = mapped_column(Text, default="", comment="用例描述")
    status: Mapped[str] = mapped_column(
        String(20),
        default="active",
        comment="状态: active/disabled"
    )
    priority: Mapped[str] = mapped_column(
        String(20),
        default="medium",
        comment="优先级: high/medium/low"
    )
    tags: Mapped[list] = mapped_column(JSON, default=list, comment="标签列表")
    steps: Mapped[list] = mapped_column(JSON, default=list, 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/performance/functional"
    )

    # 新增字段：依赖管理和参数化支持
    depends_on: Mapped[list] = mapped_column(JSON, default=list, comment="依赖用例ID列表")
    parameters: Mapped[dict] = mapped_column(JSON, default=dict, comment="参数定义")
    condition: Mapped[dict] = mapped_column(JSON, default=dict, comment="执行条件")
    order: Mapped[int] = mapped_column(Integer, default=0, comment="执行顺序")
    version: Mapped[int] = mapped_column(Integer, default=1, comment="版本号")

    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.utcnow,
        comment="创建时间"
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.utcnow,
        onupdate=datetime.utcnow,
        comment="更新时间"
    )

    # 关联模块（多对一）
    module: Mapped["Module"] = relationship(
        "Module",
        back_populates="cases"
    )

    # 关联依赖关系（一对多）
    dependencies: Mapped[list["CaseDependency"]] = relationship(
        "CaseDependency",
        foreign_keys="CaseDependency.case_id",
        back_populates="case",
        cascade="all, delete-orphan"
    )

    # 关联被依赖关系（一对多）
    dependents: Mapped[list["CaseDependency"]] = relationship(
        "CaseDependency",
        foreign_keys="CaseDependency.depends_on_case_id",
        back_populates="depends_on_case",
        cascade="all, delete-orphan"
    )

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

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

        Returns:
            dict: 用例数据字典
        """
        return {
            "id": self.id,
            "module_id": self.module_id,
            "name": self.name,
            "description": self.description,
            "status": self.status,
            "priority": self.priority,
            "tags": self.tags or [],
            "steps": self.steps or [],
            "config": self.config or {},
            "case_type": self.case_type,
            "depends_on": self.depends_on or [],
            "parameters": self.parameters or {},
            "condition": self.condition or {},
            "order": self.order,
            "version": self.version,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }
