#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：api_preset.py
模块描述：API 接口预设数据库模型定义

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

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

from app.database import Base


class ApiPreset(Base):
    """
    API 接口预设数据库模型

    将接口配置（方法、URL、请求头、请求体、认证配置等）抽象为可复用的预设，
    创建性能测试任务时只需选择预设即可自动填充接口字段。

    Attributes:
        id (str): 唯一标识 (preset_xxx)
        name (str): 预设名称，如"新建会议V3"（唯一）
        description (str): 描述，说明用途

        # 接口配置
        method (str): HTTP 方法 (GET/POST/PUT/DELETE)
        target_url (str): 目标接口完整 URL（含协议和域名）
        headers (dict): 自定义请求头
        body (dict|list): 静态请求体（与 body_template 互斥）
        body_template (dict): 请求体模板（支持 {__XXX__} 占位符替换）

        # 认证配置
        auth_required (bool): 是否需要登录 Token
        sign_request (bool): 是否需要签名 (X-RANDOM/X-TIMESTAMP/X-SIGN)
        account_key (str): 使用账号 key（superadmin/admin/user）

        # 响应捕获
        capture_rules (list): 捕获规则列表

        # 时间
        created_at (datetime): 创建时间
        updated_at (datetime): 更新时间
    """

    __tablename__ = "api_presets"

    id: Mapped[str] = mapped_column(String(64), primary_key=True, comment="预设ID (preset_xxx)")
    name: Mapped[str] = mapped_column(
        String(200), unique=True, index=True, nullable=False, comment="预设名称（唯一）"
    )
    description: Mapped[str] = mapped_column(Text, default="", comment="描述")

    # 接口配置
    method: Mapped[str] = mapped_column(String(10), default="GET", comment="HTTP方法")
    target_url: Mapped[str] = mapped_column(Text, default="", comment="目标接口完整URL")
    headers: Mapped[dict] = mapped_column(JSON, default=dict, comment="自定义请求头")
    body: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="静态请求体")
    body_template: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="请求体模板")

    # 认证配置
    auth_required: Mapped[bool] = mapped_column(Boolean, default=True, comment="是否需要登录Token")
    sign_request: Mapped[bool] = mapped_column(
        Boolean, default=False, comment="请求是否需要签名(X-RANDOM/X-TIMESTAMP/X-SIGN)"
    )
    account_key: Mapped[str] = mapped_column(String(50), default="superadmin", comment="使用账号key")

    # 登录凭据配置
    credential_name: Mapped[Optional[str]] = mapped_column(
        String(100), nullable=True, default=None, comment="凭据名称，如'超级管理员'"
    )
    login_username: Mapped[Optional[str]] = mapped_column(
        String(200), nullable=True, default=None, comment="自定义登录用户名，留空使用默认"
    )
    login_password: Mapped[Optional[str]] = mapped_column(
        String(200), nullable=True, default=None, comment="自定义登录密码，留空使用默认"
    )

    # 响应捕获
    capture_rules: Mapped[Optional[list]] = mapped_column(JSON, nullable=True, 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="更新时间"
    )

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

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

        Returns:
            dict: 预设数据字典
        """
        return {
            "id": self.id,
            "name": self.name,
            "description": self.description,
            "method": self.method,
            "target_url": self.target_url,
            "headers": self.headers or {},
            "body": self.body,
            "body_template": self.body_template,
            "auth_required": self.auth_required,
            "sign_request": self.sign_request,
            "account_key": self.account_key,
            "credential_name": self.credential_name,
            "login_username": self.login_username,
            "login_password": self.login_password,
            "capture_rules": self.capture_rules or [],
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }