"""Scene-specific text-free background planning for final-near motion renders."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from autoshorts.ideas.candidate import ValidationResult
from autoshorts.rendering.final_video_plan import FinalVideoPlan, validate_final_video_plan


@dataclass(frozen=True)
class SceneBackgroundAsset:
    scene_id: str
    provider: str
    prompt: str
    output_path: str
    renderer_owned_overlay_required: bool = True


@dataclass(frozen=True)
class SceneBackgroundPlan:
    candidate_id: str
    assets: tuple[SceneBackgroundAsset, ...]
    side_effects: tuple[str, ...] = ()
    external_calls: tuple[str, ...] = ()


_SCENE_PROMPT_NOTES = {
    "clean-demo": "clean modern laptop workspace, calm inbox dashboard glow, orderly automation demo mood",
    "weird-email": "slightly messy email-workflow atmosphere, amber warning mood, desk close-up, shallow depth of field",
    "wrong-routing": "abstract AI routing node ambience, glowing path energy, subtle red warning tension",
    "three-way-split": "minimal dark technical background with empty space for a three-branch diagram overlay",
    "final-rule": "premium minimal blue-green abstract technology background, calm final-rule energy",
}


def build_chatgpt_image_scene_background_plan(final_plan: FinalVideoPlan, *, output_dir: str | Path) -> SceneBackgroundPlan:
    validation = validate_final_video_plan(final_plan)
    if not validation.is_valid:
        raise ValueError("; ".join(validation.errors))
    root = Path(output_dir)
    assets = tuple(
        SceneBackgroundAsset(
            scene_id=scene.scene_id,
            provider="chatgpt_image_codex",
            prompt=(
                "Vertical 9:16 cinematic background for a TrueTrace AI automation short. "
                f"Scene: {scene.scene_id}. {_SCENE_PROMPT_NOTES.get(scene.scene_id, scene.asset_prompt)}. "
                "No readable text, no logos, no watermarks, no UI labels, no fake letters. "
                "Leave clean central negative space for renderer-owned cards, labels, arrows, and captions. "
                "Modern premium tech aesthetic, dark blue/green palette, realistic but not cluttered."
            ),
            output_path=str(root / f"{scene.scene_id}.png"),
            renderer_owned_overlay_required=True,
        )
        for scene in final_plan.scenes
    )
    plan = SceneBackgroundPlan(candidate_id=final_plan.candidate_id, assets=assets)
    validation = validate_scene_background_plan(plan)
    if not validation.is_valid:
        raise ValueError("; ".join(validation.errors))
    return plan


def validate_scene_background_plan(plan: SceneBackgroundPlan) -> ValidationResult:
    errors: list[str] = []
    if not plan.candidate_id.strip():
        errors.append("candidate_id is required")
    if not plan.assets:
        errors.append("at least one scene background asset is required")
    if plan.side_effects:
        errors.append("scene background plan must not have side effects")
    if plan.external_calls:
        errors.append("scene background plan must not have external calls")
    seen: set[str] = set()
    for index, asset in enumerate(plan.assets, start=1):
        if not asset.scene_id.strip():
            errors.append(f"asset {index} scene_id is required")
        if asset.scene_id in seen:
            errors.append(f"duplicate scene background asset: {asset.scene_id}")
        seen.add(asset.scene_id)
        if asset.provider != "chatgpt_image_codex":
            errors.append(f"asset {index} provider must be chatgpt_image_codex")
        if not asset.output_path.endswith(".png"):
            errors.append(f"asset {index} output_path must end with .png")
        prompt = asset.prompt.casefold()
        if "no readable text" not in prompt:
            errors.append(f"asset {index} prompt must explicitly forbid readable text")
        if "no logos" not in prompt:
            errors.append(f"asset {index} prompt must explicitly forbid logos")
        if not asset.renderer_owned_overlay_required:
            errors.append(f"asset {index} requires renderer-owned overlays")
    return ValidationResult(is_valid=not errors, errors=tuple(errors))
