"""Phase C — typed payload hints tests."""

import pytest
from recoil.execution.providers.payload_hints import (
    PayloadHints,
    WanHints, KlingHints, GoogleHints, StepRunnerHints,
    PayloadHintsValidationError,
    coerce_to_dict,
)


class TestWanHints:
    def test_construct_with_defaults(self):
        h = WanHints()
        assert h.enable_safety_checker is True
        assert h.enable_prompt_expansion is False
        assert h.seed is None

    def test_construct_with_seed(self):
        h = WanHints(seed=42)
        assert h.seed == 42

    def test_unknown_key_allowed_phase_c(self):
        h = WanHints(seed=42, unknown_key="x")
        assert h.seed == 42

    def test_as_dict_excludes_none(self):
        h = WanHints(seed=42)
        d = h.as_dict()
        assert "seed" in d
        assert d["seed"] == 42
        assert "audio_url" not in d


class TestGoogleHints:
    def test_modality_default_video(self):
        h = GoogleHints()
        assert h.modality == "video"

    def test_modality_image(self):
        h = GoogleHints(modality="image")
        assert h.modality == "image"

    def test_invalid_modality_rejected(self):
        with pytest.raises(Exception):
            GoogleHints(modality="bogus")


class TestKlingHints:
    def test_mode_default_standard(self):
        h = KlingHints()
        assert h.mode == "standard"


class TestStepRunnerHints:
    def test_partial_construct(self):
        h = StepRunnerHints(modality="video")
        assert h.modality == "video"
        assert h.multi_shots is None


class TestCoerceToDict:
    def test_none_returns_empty(self):
        assert coerce_to_dict(None) == {}

    def test_dict_passthrough(self):
        assert coerce_to_dict({"k": "v"}) == {"k": "v"}

    def test_model_dump(self):
        h = WanHints(seed=42)
        d = coerce_to_dict(h)
        assert d.get("seed") == 42
