import pytest

from autoshorts.content.brief import create_content_brief
from autoshorts.content.script_draft import create_script_draft
from autoshorts.rendering.manifest import RenderManifest, RenderSettings, build_render_manifest
from autoshorts.rendering.preview import RenderPreview, build_html_preview, validate_render_preview
from autoshorts.rendering.shot_plan import create_shot_plan


def _manifest():
    brief = create_content_brief(
        pillar_id="ai_life_systems",
        topic="AI weekly review routine",
        audience_problem="I use AI tools but still lose control of priorities.",
        payoff="a 10-minute Sunday review that keeps AI as assistant, not boss",
    )
    script = create_script_draft(brief)
    return build_render_manifest(create_shot_plan(script))


def test_build_html_preview_creates_side_effect_free_timeline_preview():
    manifest = _manifest()

    preview = build_html_preview(manifest)

    assert isinstance(preview, RenderPreview)
    assert preview.script_id == "ai_life_systems-ai-weekly-review-routine"
    assert preview.preview_type == "html_timeline"
    assert preview.side_effects == ()
    assert preview.external_calls == ()
    assert "<html" in preview.html
    assert "AI weekly review routine" in preview.html
    assert "1080x1920" in preview.html
    assert "30fps" in preview.html
    assert "first_frame_hook" in preview.html
    assert "0–3s" in preview.html
    assert "placeholders/ai_life_systems-ai-weekly-review-routine/01-first_frame_hook.png" in preview.html
    assert "If AI runs your week, you have already lost control." in preview.html


def test_validate_render_preview_accepts_default_preview():
    result = validate_render_preview(build_html_preview(_manifest()))

    assert result.is_valid is True
    assert result.errors == ()


def test_build_html_preview_rejects_invalid_manifest():
    manifest = _manifest()
    invalid = RenderManifest(
        script_id=manifest.script_id,
        title=manifest.title,
        settings=RenderSettings(width=1920, height=1080),
        timeline=manifest.timeline,
    )

    with pytest.raises(ValueError, match="render size must be vertical 1080x1920"):
        build_html_preview(invalid)


def test_validate_render_preview_rejects_side_effects_and_external_calls():
    preview = build_html_preview(_manifest())
    unsafe = RenderPreview(
        script_id=preview.script_id,
        title=preview.title,
        preview_type=preview.preview_type,
        html=preview.html,
        side_effects=("write_file",),
        external_calls=("comfyui",),
    )

    result = validate_render_preview(unsafe)

    assert result.is_valid is False
    assert "preview must not have side effects" in result.errors
    assert "preview must not call external renderers" in result.errors


def test_build_html_preview_escapes_timeline_text():
    manifest = _manifest()
    first = manifest.timeline[0]
    dangerous_item = type(first)(
        scene_purpose=first.scene_purpose,
        start_seconds=first.start_seconds,
        end_seconds=first.end_seconds,
        asset_mode=first.asset_mode,
        motion_instruction="Move <script>alert('x')</script>",
        placeholder_asset_path=first.placeholder_asset_path,
        caption_layer=type(first.caption_layer)(text="Human < approval", renderer_owned=True),
        label_layer=first.label_layer,
    )
    dangerous = RenderManifest(
        script_id=manifest.script_id,
        title=manifest.title,
        settings=manifest.settings,
        timeline=(dangerous_item,) + manifest.timeline[1:],
    )

    preview = build_html_preview(dangerous)

    assert "<script>" not in preview.html
    assert "&lt;script&gt;" in preview.html
    assert "Human &lt; approval" in preview.html
