"""
正则替换规则模型

兼容 SillyTavern 的正则系统，支持全局、角色卡、预设三种作用域。
"""
from enum import Enum
from typing import List, Optional, Dict, Any
from pydantic import BaseModel, Field
from datetime import datetime


class RegexPlacement(int, Enum):
    """
    正则应用位置（对应 SillyTavern 的 placement 数组）
    
    0: System Prompt - 系统提示词
    1: User Input - 用户输入
    2: AI Output - AI 输出
    3: Quick Reply - 快捷回复
    4: World Info - 世界书信息
    5: Reasoning/Thinking - 推理/思考内容
    """
    SYSTEM_PROMPT = 0
    USER_INPUT = 1
    AI_OUTPUT = 2
    QUICK_REPLY = 3
    WORLD_INFO = 4
    REASONING = 5


class RegexScope(str, Enum):
    """
    正则规则作用域
    
    - GLOBAL: 全局生效，对所有聊天应用
    - CHARACTER: 绑定到特定角色卡
    - PRESET: 绑定到特定预设
    """
    GLOBAL = 'global'
    CHARACTER = 'character'
    PRESET = 'preset'


class SubstituteMode(int, Enum):
    """
    替换模式
    
    对应 SillyTavern 的 substituteRegex 字段
    """
    REPLACE_ALL = 0        # 替换所有匹配
    REPLACE_FIRST = 1      # 仅替换首次匹配
    REPLACE_CAPTURED = 2   # 替换捕获组


class RegexRule(BaseModel):
    """
    单条正则替换规则
    
    完全兼容 SillyTavern 的正则规则格式
    """
    id: str = Field(..., description="规则唯一标识符 (UUID)")
    scriptName: str = Field(..., description="脚本名称（用于显示）")
    
    # 核心正则配置
    findRegex: str = Field(..., description="查找正则表达式（如：/<thinking>[\\s\\S]*?<\\/thinking>/gi）")
    replaceString: str = Field("", description="替换字符串（支持捕获组引用 $1, $2 等）")
    trimStrings: List[str] = Field(default_factory=list, description="要额外修剪的字符串数组")
    
    # 应用位置（关键！对应 SillyTavern 的 placement 数组）
    placement: List[RegexPlacement] = Field(
        default_factory=lambda: [RegexPlacement.AI_OUTPUT],
        description="应用位置数组：0=系统提示词, 1=用户输入, 2=AI输出, 3=快捷回复, 4=世界书, 5=推理内容"
    )
    
    # 替换模式
    substituteRegex: SubstituteMode = Field(
        SubstituteMode.REPLACE_ALL, 
        description="替换模式：0=全部，1=首次，2=捕获组"
    )
    
    # 作用范围控制
    markdownOnly: bool = Field(False, description="是否仅应用于 Markdown 渲染后的内容")
    promptOnly: bool = Field(False, description="是否仅应用于发送给 LLM 的提示词")
    runOnEdit: bool = Field(True, description="用户编辑消息时是否重新应用")
    
    # 消息深度控制
    minDepth: Optional[int] = Field(None, ge=0, description="最小消息深度（从最新消息开始计数，None 表示无限制）")
    maxDepth: Optional[int] = Field(None, ge=0, description="最大消息深度（None 表示无限制）")
    
    # 作用域配置
    scope: RegexScope = Field(RegexScope.GLOBAL, description="规则作用域")
    characterName: Optional[str] = Field(None, description="绑定的角色卡名称（scope=CHARACTER 时使用）")
    presetName: Optional[str] = Field(None, description="绑定的预设名称（scope=PRESET 时使用）")
    
    # 启用状态
    disabled: bool = Field(False, description="是否禁用此规则（与 enabled 相反，为了兼容 ST）")
    
    # 执行顺序
    order: int = Field(0, description="执行顺序（数值越小越先执行）")
    
    # 元数据
    createdAt: int = Field(default_factory=lambda: int(datetime.now().timestamp()), description="创建时间戳")
    updatedAt: int = Field(default_factory=lambda: int(datetime.now().timestamp()), description="最后更新时间戳")
    description: Optional[str] = Field(None, description="规则描述（可选）")


class RegexRuleset(BaseModel):
    """
    正则规则集
    
    一组正则规则的集合，可以整体导入/导出，兼容 SillyTavern 格式
    """
    id: str = Field(..., description="规则集唯一标识符 (UUID)")
    name: str = Field(..., description="规则集名称")
    description: Optional[str] = Field(None, description="规则集描述")
    
    rules: List[RegexRule] = Field(default_factory=list, description="规则列表")
    
    # 元数据
    createdAt: int = Field(default_factory=lambda: int(datetime.now().timestamp()), description="创建时间戳")
    updatedAt: int = Field(default_factory=lambda: int(datetime.now().timestamp()), description="最后更新时间戳")
    version: int = Field(1, description="版本号（用于数据迁移）")
    
    # SillyTavern 兼容性标记
    isSillyTavernFormat: bool = Field(False, description="是否为 SillyTavern 导入格式")


# ==================== 使用示例 ====================

if __name__ == '__main__':
    import json
    
    # 创建一条规则
    rule = RegexRule(
        id="example-hide-thinking-001",
        scriptName="隐藏思考标签",
        findRegex=r"<thinking>[\s\S]*?<\/thinking>",
        replaceString="",
        trimStrings=[],
        placement=[RegexPlacement.AI_OUTPUT],
        substituteRegex=SubstituteMode.REPLACE_ALL,
        markdownOnly=False,
        promptOnly=False,
        runOnEdit=True,
        minDepth=0,
        maxDepth=None,
        scope=RegexScope.GLOBAL,
        characterName=None,
        presetName=None,
        disabled=False,
        order=1,
        description="隐藏 AI 回复中的 <thinking> 标签及其内容"
    )
    
    # 创建规则集
    ruleset = RegexRuleset(
        id="ruleset-001",
        name="默认正则规则集",
        description="包含常用的文本处理规则",
        rules=[rule]
    )
    
    # 导出为 JSON（兼容 SillyTavern）
    print(json.dumps(ruleset.dict(), indent=2, ensure_ascii=False))
