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 GeneratedVideo: id: str project_id: str generation_task_id: str name: str file_url: str file_size: int duration: float width: int height: int fps: float thumbnail_url: str | None = None status: str = "completed" review_status: str = "pending_review" generation_params: dict[str, Any] = field(default_factory=dict) video_fingerprint: dict[str, Any] | None = None is_duplicate: bool = False duplicate_of: str | None = None generated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc)) created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc)) @classmethod def create( cls, project_id: str, generation_task_id: str, name: str, file_url: str, *, file_size: int = 0, duration: float = 0.0, width: int = 0, height: int = 0, fps: float = 0.0, thumbnail_url: str | None = None, generation_params: dict[str, Any] | None = None, ) -> "GeneratedVideo": if not project_id.strip(): raise ValueError("project_id cannot be empty") if not generation_task_id.strip(): raise ValueError("generation_task_id cannot be empty") if not name.strip(): raise ValueError("name cannot be empty") if not file_url.strip(): raise ValueError("file_url cannot be empty") return cls( id=uuid4().hex, project_id=project_id.strip(), generation_task_id=generation_task_id.strip(), name=name.strip(), file_url=file_url.strip(), file_size=file_size, duration=duration, width=width, height=height, fps=fps, thumbnail_url=thumbnail_url, generation_params=generation_params or {}, )