"""
@FileName: base_models.py
@Description: 基本模型
@Author: HiPeng
@Github: https://github.com/neopen/video-shot-agent
@Time: 2026/1/18 14:31
"""
import uuid
from datetime import datetime
from enum import Enum, unique
from typing import Optional, List

from pydantic import BaseModel, Field

from penshot.utils.enum_utils import EnumPrefixMatcher


class PrefixEnum(Enum):
    """支持忽略大小写和前缀匹配的枚举基类"""

    @classmethod
    def match_prefix(cls, text, case_sensitive=False):
        text = text if case_sensitive else text.lower()
        for member in cls:
            value = member.value if case_sensitive else member.value.lower()
            if value.startswith(text):
                return member
        return None

    @classmethod
    def match_all_prefix(cls, text, case_sensitive=False):
        text = text if case_sensitive else text.lower()
        return [
            member for member in cls
            if (member.value if case_sensitive else member.value.lower()).startswith(text)
        ]

    @classmethod
    def match_by_prefix(cls, text: str, min_length: int = 3) -> Optional['Enum']:
        """
        根据前缀匹配枚举值（默认前三位相同即匹配）

        Args:
            text: 输入文本
            min_length: 最小匹配长度，默认3

        Returns:
            匹配的枚举成员，未匹配返回 None
        """
        if not text or len(text) < min_length:
            return None

        # 统一转小写，忽略大小写
        text_prefix = text[:min_length].lower()

        for member in cls:
            value = str(member.value).lower()
            if len(value) >= min_length and value[:min_length] == text_prefix:
                return member

        return None

    @classmethod
    def match_all_by_prefix(cls, text: str, min_length: int = 3) -> List['Enum']:
        """返回所有前缀匹配的枚举成员"""
        if not text or len(text) < min_length:
            return []

        text_prefix = text[:min_length].lower()
        results = []

        for member in cls:
            value = str(member.value).lower()
            if len(value) >= min_length and value[:min_length] == text_prefix:
                results.append(member)

        return results

    @classmethod
    def is_valid_prefix(cls, text: str, min_length: int = 3) -> bool:
        """检查前缀是否有效"""
        return cls.match_by_prefix(text, min_length) is not None


class PrefixValueEnum(Enum):
    """枚举值为前缀，支持匹配完整输入值"""

    @classmethod
    def match_by_input(cls, input_text: str, min_length: int = 3) -> Optional['Enum']:
        """
        根据完整输入值匹配枚举（枚举值是前缀）

        规则：输入值的前缀与枚举值比较，前三位相同即匹配

        Args:
            input_text: 完整输入值（如 "runway_gen2"）
            min_length: 最小匹配长度，默认 3

        Returns:
            匹配的枚举成员，未匹配返回 None
        """
        if not input_text:
            return None

        input_lower = input_text.lower()

        for member in cls:
            enum_value = str(member.value).lower()

            # 枚举值长度必须 >= min_length
            if len(enum_value) < min_length:
                continue

            # 检查输入值是否以枚举值开头（前缀匹配）
            if input_lower.startswith(enum_value):
                return member

        return None

    @classmethod
    def match_all_by_input(cls, input_text: str, min_length: int = 3) -> List['Enum']:
        """返回所有匹配的枚举成员"""
        if not input_text:
            return []

        input_lower = input_text.lower()
        results = []

        for member in cls:
            enum_value = str(member.value).lower()

            if len(enum_value) >= min_length and input_lower.startswith(enum_value):
                results.append(member)

        return results

    @classmethod
    def is_valid_input(cls, input_text: str, min_length: int = 3) -> bool:
        """检查输入值是否有效"""
        return cls.match_by_input(input_text, min_length) is not None


# ==================== 基础枚举和类型定义 ====================
class ScriptType(str, Enum):
    """剧本格式类型"""
    NATURAL_LANGUAGE = "natural_language"  # 自然语言描述
    AI_STORYBOARD = "ai_storyboard"  # AI分镜脚本
    STRUCTURED_SCENE = "structured_scene"  # 结构化场景描述
    STANDARD_SCRIPT = "standard_script"  # 标准剧本格式
    DIALOGUE_ONLY = "dialogue_only"  # 纯对话
    MIXED_FORMAT = "mixed_format"  # 混合格式


class ElementType(str, Enum):
    SCENE = "scene"  # 场景描述
    DIALOGUE = "dialogue"  # 对话节点
    ACTION = "action"  # 动作节点
    TRANSITION = "transition"
    SILENCE = "silence"
    UNKNOWN = "unknown"


class AgentMode(str, Enum):
    """agent 实现的模式"""
    LLM = "llm"  # 基于 LLM 实现
    RULE = "rule"  # 基于本地规则


class VideoStyle(str, Enum):
    """视频风格/场景枚举（适用于背景声）"""
    # 逼真写实
    REALISTIC = 'realistic'
    # 动漫
    ANIME = 'anime'
    # 电影
    CINEMATIC = 'cinematic'
    # 卡通
    CARTOON = 'cartoon'
    # 风格化
    STYLIZED = "stylized"
    # 氛围/环境
    AMBIENT = "ambient"


class VideoModelType(str, PrefixValueEnum):
    """AI视频模型类型枚举"""
    RUNWAY_GEN2 = "runway_gen2"  # Runway Gen-2
    RUNWAY = "runway"
    SORA = "sora"
    VEO = "veo"
    Pika = "pika"
    MIDJOURNEY = "midjourney"
    STABLE = "stable"
    DALLE = "dalle"


class AudioModelType(str, Enum):
    """AI音频模型类型枚举"""
    XTTSv2 = "XTTSv2"  # 台词、旁白、人声
    AUDIOLDM_3 = "AudioLDM_3"  # 背景声、环境音、音效
    BARK = "Bark"  # 创造性语音（带语气词）
    ELEVENLABS = "ElevenLabs"  # 商业API（如果需要）
    AZURE_TTS = "Azure_TTS"  # 商业TTS
    OPENAI_TTS = "OpenAI_TTS"  # OpenAI TTS


@unique
class GenerationStatus(str, Enum):
    """生成状态"""
    PENDING = "pending"  # 等待生成
    GENERATING = "generating"  # 生成中
    SUCCESS = "success"  # 成功
    FAILED = "failed"  # 失败
    NEEDS_RETRY = "needs_retry"  # 需要重试
    NEEDS_MANUAL_FIX = "needs_manual_fix"  # 需要手动修复


# ==================== 基础模型类 ====================
class BaseMetadata(BaseModel):
    """时间戳混合类"""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    created_at: datetime = Field(default_factory=datetime.now)
    updated_at: Optional[datetime] = None
    version: str = Field(default="1.0", description="模型版本")


def parse_model_name(full_name: str) -> Optional[VideoModelType]:
    """从完整模型名解析基础模型"""
    return EnumPrefixMatcher.match(VideoModelType, full_name.strip(), min_length=3)
