"""StoryboardRunner — modality ``storyboard``.

Thin wrapper over StepRunner.execute_keyframe for storyboard strip generation.
The board builder assembles the prompt and payload directly; this runner only
translates the dispatch payload into named execute_keyframe kwargs and adapts
the StepResult into a RunResult.
"""

from __future__ import annotations

import time
from pathlib import Path
from typing import Any, Optional

from recoil.pipeline.core.registry import MODALITY_STORYBOARD, RunResult
from recoil.pipeline.core.runners._shared import (
    _failure_metadata_production as _failure_metadata,
)
from recoil.pipeline.core.runners.image_runner import _step_result_to_run_result


class StoryboardRunner:
    """ModalityRunner for ``storyboard`` — single storyboard-strip image."""

    modality: str = MODALITY_STORYBOARD

    def __init__(self, step_runner) -> None:
        self._step_runner = step_runner

    def run(self, payload: dict) -> RunResult:
        shot_id = payload.get("shot_id")
        prompt = payload.get("prompt")
        model = payload.get("model")

        if not shot_id or not prompt or not model:
            return RunResult(
                id=f"{shot_id or 'unknown'}_storyboard_{int(time.time())}",
                modality=self.modality,
                success=False,
                error=(
                    f"StoryboardRunner payload missing required keys: "
                    f"shot_id={shot_id!r}, prompt={'...' if prompt else None!r}, "
                    f"model={model!r}"
                ),
                metadata=_failure_metadata(),
            )

        def _to_path(v: Any) -> Optional[Path]:
            if v is None:
                return None
            return v if isinstance(v, Path) else Path(v)

        def _to_path_list(v: Any) -> Optional[list[Path]]:
            if v is None:
                return None
            return [p if isinstance(p, Path) else Path(p) for p in v]

        try:
            step_result = self._step_runner.execute_keyframe(
                shot_id=shot_id,
                prompt=prompt,
                model=model,
                reference_images=_to_path_list(payload.get("reference_images")),
                quality=payload.get("quality"),
                size_override=payload.get("size_override"),
                aspect_ratio=payload.get("aspect_ratio"),
                inputs_snapshot=payload.get("inputs_snapshot"),
                save_dir=_to_path(payload.get("save_dir")),
                filename_stem=payload.get("filename_stem"),
                sidecar_extra=payload.get("sidecar_extra"),
            )
        except Exception as e:  # noqa: BLE001
            return RunResult(
                id=f"{shot_id}_storyboard_{int(time.time())}",
                modality=self.modality,
                success=False,
                error=f"{type(e).__name__}: {e}",
                metadata=_failure_metadata(),
            )

        return _step_result_to_run_result(step_result, shot_id, self.modality)
