import pytest
import respx
from httpx import Response
from app.pipeline import review


@pytest.mark.asyncio
@respx.mock
async def test_review_returns_pass_when_above_threshold(monkeypatch):
    monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
    body = {"content": [{"type": "text", "text":
        '{"metadata_quality":{"score":80,"notes":"x"},'
        '"policy_compliance":{"score":90,"issues":[]},'
        '"viewer_experience":{"score":75,"notes":"y"},'
        '"trend_alignment":{"score":70,"matched_keywords":["lofi"]},'
        '"summary":"good"}'}]}
    respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(200, json=body))
    result = await review.run_4_axis(
        pipeline={"id": 1}, track={"title": "x", "genre": "lo-fi", "bpm": 85},
        video_meta={"length_sec": 120, "resolution": "1920x1080"},
        metadata={"title": "Y", "description": "Z", "tags": ["lofi"], "category_id": 10},
        thumbnail_url="/m/x.jpg", trend_top=["lofi"],
        weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
        threshold=60,
    )
    assert result["verdict"] == "pass"
    expected_total = 0.25 * 80 + 0.30 * 90 + 0.25 * 75 + 0.20 * 70
    assert result["weighted_total"] == pytest.approx(expected_total, abs=0.01)


@pytest.mark.asyncio
@respx.mock
async def test_review_fail_below_threshold(monkeypatch):
    monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
    body = {"content": [{"type": "text", "text":
        '{"metadata_quality":{"score":40,"notes":"x"},'
        '"policy_compliance":{"score":50,"issues":[]},'
        '"viewer_experience":{"score":30,"notes":"y"},'
        '"trend_alignment":{"score":20,"matched_keywords":[]},'
        '"summary":"bad"}'}]}
    respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(200, json=body))
    result = await review.run_4_axis(
        pipeline={"id": 2}, track={"title": "x", "genre": "lo-fi", "bpm": 85},
        video_meta={"length_sec": 120, "resolution": "1920x1080"},
        metadata={"title": "Y", "description": "Z", "tags": [], "category_id": 10},
        thumbnail_url="/m/x.jpg", trend_top=[],
        weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
        threshold=60,
    )
    assert result["verdict"] == "fail"


@pytest.mark.asyncio
@respx.mock
async def test_review_heuristic_fallback_on_llm_error(monkeypatch):
    monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
    respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(500))
    result = await review.run_4_axis(
        pipeline={"id": 3}, track={"title": "x", "genre": "lo-fi", "bpm": 85, "duration_sec": 120},
        video_meta={"length_sec": 120, "resolution": "1920x1080"},
        metadata={"title": "Y" * 30, "description": "Z" * 200, "tags": ["a", "b", "c", "d", "e"], "category_id": 10},
        thumbnail_url="/m/x.jpg", trend_top=["lofi"],
        weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
        threshold=60,
    )
    assert result["used_fallback"] is True
    assert "weighted_total" in result


@pytest.mark.asyncio
async def test_review_heuristic_when_no_api_key(monkeypatch):
    monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)
    result = await review.run_4_axis(
        pipeline={"id": 4}, track={"title": "x", "genre": "lo-fi", "bpm": 85, "duration_sec": 120},
        video_meta={"length_sec": 120, "resolution": "1920x1080"},
        metadata={"title": "Test Title", "description": "Description here, more text " * 5,
                  "tags": ["lofi", "study", "chill", "ambient", "instrumental"], "category_id": 10},
        thumbnail_url="/m/x.jpg", trend_top=["lofi"],
        weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
        threshold=60,
    )
    assert result["used_fallback"] is True
    # 휴리스틱: 좋은 메타+영상길이 일치+태그 트렌드 겹침 → pass 기대
    assert result["verdict"] == "pass"
