"""SceneStillSyncService 내부 3-way 분해 계약 타입.

P3-1 (W4): loader → normalizer → writer 파이프라인의 데이터 계약을 정의.
외부 API(SceneStillSyncService.sync_from_checkpoint)는 변경 없음.
"""
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Set, Tuple

# (scene_index, shot_index or None) — shot-based와 legacy 모두 커버
StillKey = Tuple[int, Optional[int]]


@dataclass
class CheckpointBundle:
    """SceneStillCheckpointLoader가 산출하는 체크포인트 덤프.

    Normalizer/Writer는 이 번들만 읽고 `_load_cp`에 다시 접근하지 않는다.
    """

    # scene_detail — 메인 루프의 입력
    scenes: List[Dict[str, Any]] = field(default_factory=list)
    sd_completed: bool = False
    # Codex P1-2 (2026-05-01): partial 상태 cp 기반 sync 시 stale 마킹/dep 초기화 skip.
    # 부분 cp가 비포함 row를 정상 누락으로 처리해 이미지 연결 끊는 사고 방지.
    sd_partial: bool = False

    # shot_dependency — dependent_scene_id 갱신용
    shot_deps: List[Dict[str, Any]] = field(default_factory=list)
    shot_dep_completed: bool = False

    # shot_validator + shot_selection — scene별 shot 정보
    shot_info_by_scene: Dict[int, List[Dict[str, Any]]] = field(default_factory=dict)
    selected_flag_by_scene: Dict[int, Set[int]] = field(default_factory=dict)

    # scene_director — 씬 단위 VE / audio / hallucination
    scene_director_ve: Dict[int, List[str]] = field(default_factory=dict)
    scene_director_audio: Dict[int, List[str]] = field(default_factory=dict)
    scene_director_hall: Dict[int, List[str]] = field(default_factory=dict)

    # shot_director — (scene, shot) 단위 VE
    shot_director_ve_map: Dict[Tuple[int, int], List[str]] = field(default_factory=dict)

    # scene_dependency (legacy) — shot_deps 비어있을 때 fallback
    dep_map: Dict[str, Dict[str, Any]] = field(default_factory=dict)

    # scene_summary — shot-level 전파
    scene_summaries: List[Dict[str, Any]] = field(default_factory=list)

    # shot_cinematography + scene_cinematography (legacy)
    shot_cine_shots: List[Dict[str, Any]] = field(default_factory=list)
    scene_cine_scenes: List[Dict[str, Any]] = field(default_factory=list)


@dataclass
class EntityMaps:
    """entity_canon 조회 결과 — normalizer가 visible_entities 해석할 때 사용."""

    name_to_id: Dict[str, str] = field(default_factory=dict)
    name_to_short: Dict[str, str] = field(default_factory=dict)
    short_to_id: Dict[str, str] = field(default_factory=dict)
    short_to_name: Dict[str, str] = field(default_factory=dict)


@dataclass
class PlannedStill:
    """Normalizer가 작성, Writer가 UPSERT하는 한 row의 설계도.

    `columns`에는 SceneStill 모델의 대부분의 필드가 들어가고,
    `still_index`/`scene_index`/`t2i_composer_version`은 writer가 명시적으로 처리.
    """

    key: StillKey
    still_index: int
    scene_index: int
    t2i_composer_version: str
    columns: Dict[str, Any] = field(default_factory=dict)
