"""查重记录领域实体。"""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any
from uuid import uuid4


@dataclass(slots=True)
class DuplicateSegment:
    """重复片段 — 描述上传视频中的一段与已有视频的匹配关系。"""

    id: str
    source_start: float
    source_end: float
    matched_video_id: str
    matched_video_name: str
    matched_start: float
    matched_end: float
    similarity: float  # 0-100

    @classmethod
    def create(
        cls,
        source_start: float,
        source_end: float,
        matched_video_id: str,
        matched_video_name: str,
        matched_start: float,
        matched_end: float,
        similarity: float,
    ) -> "DuplicateSegment":
        if source_start < 0 or source_end <= source_start:
            raise ValueError("invalid source segment range")
        if matched_start < 0 or matched_end <= matched_start:
            raise ValueError("invalid matched segment range")
        if not 0 <= similarity <= 100:
            raise ValueError("similarity must be between 0 and 100")
        return cls(
            id=uuid4().hex,
            source_start=source_start,
            source_end=source_end,
            matched_video_id=matched_video_id,
            matched_video_name=matched_video_name,
            matched_start=matched_start,
            matched_end=matched_end,
            similarity=similarity,
        )


@dataclass(slots=True)
class DuplicationRecord:
    """查重记录 — 一次视频查重请求的完整生命周期。"""

    id: str
    user_id: str
    filename: str
    file_size: int
    storage_key: str  # OSS 对象键
    duration_seconds: float = 0.0
    status: str = "pending"  # pending / processing / completed / failed
    duplicate_rate: float | None = None  # 0-100
    duplicate_count: int = 0
    video_fingerprint: dict[str, Any] | None = None
    error_message: str = ""
    segments: list[DuplicateSegment] = field(default_factory=list)
    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,
        user_id: str,
        filename: str,
        file_size: int,
        storage_key: str,
        *,
        duration_seconds: float = 0.0,
    ) -> "DuplicationRecord":
        if not user_id.strip():
            raise ValueError("user_id cannot be empty")
        if not filename.strip():
            raise ValueError("filename cannot be empty")
        if file_size <= 0:
            raise ValueError("file_size must be positive")
        return cls(
            id=uuid4().hex,
            user_id=user_id.strip(),
            filename=filename.strip(),
            file_size=file_size,
            storage_key=storage_key,
            duration_seconds=duration_seconds,
        )

    def mark_processing(self) -> None:
        self.status = "processing"
        self.updated_at = datetime.now(timezone.utc)

    def mark_completed(self, duplicate_rate: float, duplicate_count: int, segments: list[DuplicateSegment]) -> None:
        if not 0 <= duplicate_rate <= 100:
            raise ValueError("duplicate_rate must be between 0 and 100")
        self.status = "completed"
        self.duplicate_rate = duplicate_rate
        self.duplicate_count = duplicate_count
        self.segments = segments
        self.updated_at = datetime.now(timezone.utc)

    def mark_failed(self, error_message: str) -> None:
        self.status = "failed"
        self.error_message = error_message
        self.updated_at = datetime.now(timezone.utc)

    def can_retry(self) -> bool:
        """
        判断是否可重试。

        仅 failed 状态的记录允许重试，防止误操作已完成的记录。

        Returns:
            True 表示可以重试
        """
        return self.status == "failed"

    def reset_for_retry(self) -> None:
        """
        重置记录以重新查重。

        清空查重结果和错误信息，状态回到 pending。
        调用前应先通过 can_retry() 确认状态合法。
        """
        self.status = "pending"
        self.duplicate_rate = None
        self.duplicate_count = 0
        self.error_message = ""
        self.segments = []
        self.video_fingerprint = None
        self.updated_at = datetime.now(timezone.utc)
