from pathlib import Path

import pytest
from PIL import Image

from autoshorts.content.brief import create_content_brief
from autoshorts.content.script_draft import create_script_draft
from autoshorts.rendering.local_frame_writer import (
    LocalFrameWriteResult,
    localize_frame_copy,
    wrap_text_to_pixel_width,
    write_local_preview_frames,
)
from autoshorts.rendering.local_preview import LocalPreviewPlan, build_local_preview_plan
from autoshorts.rendering.manifest import build_render_manifest
from autoshorts.rendering.shot_plan import create_shot_plan


def _plan():
    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_local_preview_plan(build_render_manifest(create_shot_plan(script)))


def test_write_local_preview_frames_writes_valid_png_scene_cards(tmp_path):
    plan = _plan()

    result = write_local_preview_frames(plan, output_dir=tmp_path, approval_language="de")

    assert isinstance(result, LocalFrameWriteResult)
    assert result.script_id == "ai_life_systems-ai-weekly-review-routine"
    assert result.output_dir == str(tmp_path)
    assert result.side_effects == ("write_png",)
    assert result.external_calls == ()
    assert len(result.frame_paths) == len(plan.frames)
    assert result.frame_paths[0].endswith("frame-01-first_frame_hook.png")

    first_path = Path(result.frame_paths[0])
    assert first_path.exists()
    assert first_path.stat().st_size > 0
    with Image.open(first_path) as image:
        assert image.format == "PNG"
        assert image.size == (540, 960)


def test_write_local_preview_frames_preserves_plan_order_and_paths(tmp_path):
    plan = _plan()

    result = write_local_preview_frames(plan, output_dir=tmp_path, approval_language="de")

    assert [Path(path).name for path in result.frame_paths] == [
        "frame-01-first_frame_hook.png",
        "frame-02-pattern_interrupt.png",
        "frame-03-core_explanation.png",
        "frame-04-screen_or_card_visual.png",
        "frame-05-cta.png",
    ]


def test_write_local_preview_frames_rejects_invalid_plan(tmp_path):
    plan = _plan()
    invalid = LocalPreviewPlan(
        script_id=plan.script_id,
        title=plan.title,
        width=1920,
        height=1080,
        fps=plan.fps,
        output_dir=plan.output_dir,
        frames=plan.frames,
        side_effects=plan.side_effects,
        external_calls=plan.external_calls,
    )

    with pytest.raises(ValueError, match="preview size must be vertical"):
        write_local_preview_frames(invalid, output_dir=tmp_path)


def test_write_local_preview_frames_rejects_output_dir_outside_runtime_area(tmp_path):
    plan = _plan()
    unsafe_dir = tmp_path / ".." / "unsafe"

    with pytest.raises(ValueError, match="output_dir must be explicit and normalized"):
        write_local_preview_frames(plan, output_dir=unsafe_dir)


def test_localize_frame_copy_defaults_to_german_approval_preview_text():
    frame = _plan().frames[0]

    copy = localize_frame_copy(frame, language="de")

    assert copy.scene_label == "AUFMERKSAMKEIT"
    assert copy.caption_text == "Wenn KI deine Woche steuert, hast du die Kontrolle bereits abgegeben."
    assert copy.asset_label == "Text-Overlay"
    assert copy.motion_text == "Schneller Einstieg mit grossem Hook-Text; kein Text im Bildmaterial eingebrannt."


def test_wrap_text_to_pixel_width_keeps_each_line_within_readable_bounds():
    lines = wrap_text_to_pixel_width(
        "Wenn KI deine Woche steuert, hast du die Kontrolle bereits abgegeben.",
        max_width_px=360,
        font_size=30,
    )

    assert len(lines) >= 2
    assert all(line.strip() for line in lines)
    assert all(len(line) <= 24 for line in lines)
