"""EditPlanClip domain entity for Phase 8 模板编排引擎.

剪辑计划中的具体片段实例，关联 EditPlan 和 TemplateClipConfig，
包含实际素材、实际文案、排序和时长等信息。
"""

from __future__ import annotations

import sys
from dataclasses import dataclass, field
from datetime import datetime, timezone

if sys.version_info >= (3, 11):
    from enum import StrEnum
else:
    from enum import Enum

    class StrEnum(str, Enum):
        pass


from typing import Any
from uuid import uuid4


class EditPlanClipStatus(StrEnum):
    """片段状态"""

    PENDING = "pending"  # 待处理（素材未就绪）
    READY = "ready"  # 就绪（素材已就绪，可渲染）
    RENDERED = "rendered"  # 已渲染
    FAILED = "failed"  # 渲染失败


@dataclass(slots=True)
class EditPlanClip:
    """剪辑计划片段

    表示 EditPlan 中的一个具体片段实例，包含实际素材、文案和渲染状态。
    可选地关联 TemplateClipConfig 以继承模板规则。
    """

    id: str
    plan_id: str
    clip_type: str
    order: int
    template_clip_config_id: str = ""
    asset_id: str = ""
    text_content: str = ""
    start_time: float = 0.0
    duration: float = 0.0
    transition_effect: str = "cut"
    status: EditPlanClipStatus = EditPlanClipStatus.PENDING
    config: dict[str, Any] = field(default_factory=dict)
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

    @classmethod
    def create(
        cls,
        plan_id: str,
        clip_type: str,
        order: int,
        *,
        template_clip_config_id: str = "",
        asset_id: str = "",
        text_content: str = "",
        start_time: float = 0.0,
        duration: float = 0.0,
        transition_effect: str = "cut",
        config: dict[str, Any] | None = None,
    ) -> EditPlanClip:
        """创建剪辑计划片段"""
        if not plan_id.strip():
            raise ValueError("plan_id 不能为空")
        if not clip_type.strip():
            raise ValueError("clip_type 不能为空")
        if start_time < 0:
            raise ValueError("start_time 不能为负数")
        if duration < 0:
            raise ValueError("duration 不能为负数")

        return cls(
            id=uuid4().hex,
            plan_id=plan_id.strip(),
            clip_type=clip_type.strip(),
            order=order,
            template_clip_config_id=template_clip_config_id.strip() if template_clip_config_id else "",
            asset_id=asset_id.strip() if asset_id else "",
            text_content=text_content.strip(),
            start_time=start_time,
            duration=duration,
            transition_effect=transition_effect.strip() or "cut",
            status=EditPlanClipStatus.PENDING,
            config=config or {},
        )

    def assign_asset(self, asset_id: str) -> None:
        """分配素材"""
        if not asset_id.strip():
            raise ValueError("asset_id 不能为空")
        self.asset_id = asset_id.strip()
        self.updated_at = datetime.now(timezone.utc)

    def mark_ready(self) -> None:
        """标记为就绪"""
        if self.status != EditPlanClipStatus.PENDING:
            raise ValueError(f"只有 pending 状态的片段可以标记就绪，当前状态: {self.status}")
        self.status = EditPlanClipStatus.READY
        self.updated_at = datetime.now(timezone.utc)

    def mark_rendered(self) -> None:
        """标记为已渲染"""
        if self.status != EditPlanClipStatus.READY:
            raise ValueError(f"只有 ready 状态的片段可以标记已渲染，当前状态: {self.status}")
        self.status = EditPlanClipStatus.RENDERED
        self.updated_at = datetime.now(timezone.utc)

    def mark_failed(self) -> None:
        """标记为失败"""
        if self.status != EditPlanClipStatus.READY:
            raise ValueError(f"只有 ready 状态的片段可以标记失败，当前状态: {self.status}")
        self.status = EditPlanClipStatus.FAILED
        self.updated_at = datetime.now(timezone.utc)

    @property
    def end_time(self) -> float:
        """片段结束时间"""
        return self.start_time + self.duration

    @property
    def has_asset(self) -> bool:
        """是否已分配素材"""
        return bool(self.asset_id)
