import pytest

from autoshorts.ideas.candidate import VideoCandidate, validate_candidate
from autoshorts.ideas.testbatch import TestBatch, renderable_candidates, validate_testbatch
from autoshorts.review.package import ReviewPackage
from autoshorts.scripting.quality import ScriptQualityScore


def _good_score() -> ScriptQualityScore:
    return ScriptQualityScore(
        hook_strength=9,
        novelty=8,
        clarity=9,
        retention=8,
        ai_slop_risk=2,
        policy_risk="low",
    )


def _weak_score() -> ScriptQualityScore:
    return ScriptQualityScore(
        hook_strength=5,
        novelty=5,
        clarity=6,
        retention=5,
        ai_slop_risk=8,
        policy_risk="low",
    )


def _candidate(**overrides) -> VideoCandidate:
    data = {
        "candidate_id": "vid-001",
        "pillar": "ai_life_systems",
        "title": "AI ist ein schlechter Gott, aber ein guter Diener",
        "platforms": ("youtube", "tiktok"),
        "duration_seconds": 34,
        "hook": "AI sollte dir dienen, nicht dich führen.",
        "script_outline": (
            "Scene 1: AI chaos. Scene 2: controlled system. Scene 3: human approval gate."
        ),
        "visual_concept": "Cinematic desk setup, phone automations, calm human-in-control framing.",
        "caption": "KI als Werkzeug, nicht als Wertekompass.",
        "cta": "Follow for practical AI life systems.",
        "hashtags": ("#AI", "#Productivity"),
        "quality_score": _good_score(),
        "policy_notes": ("No fake earnings claims",),
        "hypothesis": "Values-first AI positioning gets more saves than hype content.",
    }
    data.update(overrides)
    return VideoCandidate(**data)


def test_candidate_validation_accepts_complete_growth_candidate():
    candidate = _candidate()

    result = validate_candidate(candidate)

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


def test_candidate_validation_rejects_missing_hook_and_bad_duration():
    candidate = _candidate(hook="", duration_seconds=4)

    result = validate_candidate(candidate)

    assert result.is_valid is False
    assert "hook is required" in result.errors
    assert "duration_seconds must be between 10 and 180" in result.errors


def test_candidate_can_be_converted_to_review_package():
    candidate = _candidate()

    package = candidate.to_review_package(preview_path="data/local_motion_renders/vid-001.mp4")

    assert isinstance(package, ReviewPackage)
    assert package.candidate_id == "vid-001"
    assert package.title == candidate.title
    assert package.script_summary == candidate.script_outline
    assert package.platforms == ("youtube", "tiktok")
    assert package.preview_path == "data/local_motion_renders/vid-001.mp4"


def test_testbatch_validation_rejects_duplicate_candidate_ids():
    batch = TestBatch(
        batch_id="batch-001",
        candidates=(
            _candidate(candidate_id="dup"),
            _candidate(candidate_id="dup", title="Another title"),
        ),
    )

    result = validate_testbatch(batch)

    assert result.is_valid is False
    assert "candidate ids must be unique" in result.errors


def test_testbatch_validation_requires_at_least_one_candidate():
    batch = TestBatch(batch_id="empty", candidates=())

    result = validate_testbatch(batch)

    assert result.is_valid is False
    assert "at least one candidate is required" in result.errors


def test_renderable_candidates_filters_by_candidate_validity_and_quality_gate():
    valid = _candidate(candidate_id="valid")
    weak = _candidate(candidate_id="weak", quality_score=_weak_score())
    invalid = _candidate(candidate_id="invalid", hook="")
    batch = TestBatch(batch_id="batch-001", candidates=(valid, weak, invalid))

    selected = renderable_candidates(batch)

    assert selected == (valid,)


def test_candidate_validation_rejects_unknown_platforms():
    candidate = _candidate(platforms=("youtube", "linkedin"))

    result = validate_candidate(candidate)

    assert result.is_valid is False
    assert "unsupported platform: linkedin" in result.errors
