from __future__ import annotations

import json
from pathlib import Path

import pytest

from autoshorts.website_companion import (
    build_update_gate,
    build_website_candidate,
    build_website_companion_package,
    export_companion_candidate,
    resolve_review_video_path,
    validate_companion_spec,
)


def review_package(tmp_path: Path) -> dict[str, object]:
    video = tmp_path / "review.mp4"
    video.write_bytes(b"fake-video")
    return {
        "candidate_id": "erf-018-fake-reviews",
        "version": "v1",
        "title": "Fake Reviews Have One Easy Tell",
        "sha256": "video-sha",
        "posting_pack_sha256": "pack-sha",
        "approval_command": "APPROVED_FOR_PRIVATE_YOUTUBE_UPLOAD erf-018-fake-reviews v1 video-sha pack-sha",
        "media_cache_path": str(video),
        "output": str(tmp_path / "missing.mp4"),
    }


def companion_spec() -> dict[str, object]:
    return {
        "id": "fake-reviews",
        "slug": "fake-reviews",
        "title": "Fake Reviews: What to check before you trust five stars",
        "shortTitle": "Fake Reviews",
        "hook": "A wall of perfect reviews can make a risky shop feel safe.",
        "category": "Shopping Red Flags",
        "riskLevel": "medium",
        "visibleScreen": "A shopping page with many similar five-star reviews and repeated phrases.",
        "redFlag": "Many reviews sound copied, vague, or posted in a short time window.",
        "whyItWorks": "People use reviews as social proof.",
        "saferMove": "Read the newest low-star reviews before you buy.",
        "ifAlreadyClicked": ["Save the receipt and watch for shipping problems."],
        "checklist": ["Do many reviews use the same words?"],
        "videoUrl": None,
        "visualBrief": "Direct phone-screen view of a suspicious review section; no fake brands, no real URLs, readable example UI only.",
        "related": ["delivery-sms-trap"],
        "toolRelevance": "Usually no tool is required.",
        "affiliateCategory": None,
        "seoTitle": "Fake reviews: red flags before you trust ratings",
        "metaDescription": "Learn how fake reviews make risky shops look safe.",
        "socialTitle": "Fake Reviews: One red flag before you buy",
        "body": "Fake reviews make a risky shop look safer than it is.",
    }


def test_build_website_candidate_merges_review_source() -> None:
    candidate = build_website_candidate(review={"candidate_id": "erf-018-fake-reviews", "version": "v1"}, spec=companion_spec())

    assert candidate["slug"] == "fake-reviews"
    assert candidate["source"]["candidate_id"] == "erf-018-fake-reviews"
    assert candidate["source"]["version"] == "v1"
    assert candidate["related"] == ["delivery-sms-trap"]
    assert candidate["screenImageAlt"] == companion_spec()["visibleScreen"]
    assert candidate["visualBrief"].startswith("Direct phone-screen view")


def test_validate_companion_spec_rejects_missing_required_field() -> None:
    spec = companion_spec()
    del spec["saferMove"]

    with pytest.raises(ValueError, match="saferMove"):
        validate_companion_spec(spec)


def test_resolve_review_video_path_prefers_existing_media_cache(tmp_path: Path) -> None:
    review = review_package(tmp_path)

    assert resolve_review_video_path(review) == Path(str(review["media_cache_path"]))


def test_export_companion_candidate_writes_website_candidate_json(tmp_path: Path) -> None:
    review_path = tmp_path / "review.json"
    spec_path = tmp_path / "spec.json"
    website_root = tmp_path / "website"
    review_path.write_text(json.dumps(review_package(tmp_path)), encoding="utf-8")
    spec_path.write_text(json.dumps(companion_spec()), encoding="utf-8")

    plan = export_companion_candidate(
        review_package_path=review_path,
        companion_spec_path=spec_path,
        website_root=website_root,
        run_generator=False,
    )

    assert plan.slug == "fake-reviews"
    assert plan.video_path == Path(json.loads(review_path.read_text())["media_cache_path"])
    assert plan.candidate_json_path.exists()
    payload = json.loads(plan.candidate_json_path.read_text(encoding="utf-8"))
    assert payload["source"]["approval_command"].startswith("APPROVED_FOR_PRIVATE_YOUTUBE_UPLOAD")
    assert payload["shortTitle"] == "Fake Reviews"


def test_build_update_gate_blocks_unsafe_payload(tmp_path: Path) -> None:
    review = review_package(tmp_path)
    candidate = build_website_candidate(review=review, spec=companion_spec())
    candidate["redFlag"] = "A fake page sends you to badsite.com."

    gate = build_update_gate(review, candidate, Path(str(review["media_cache_path"])))

    assert not gate.allowed
    assert not gate.no_real_scam_data
    assert gate.website_payload_sha256


def test_website_companion_package_is_approval_bound(tmp_path: Path) -> None:
    review_path = tmp_path / "review.json"
    spec_path = tmp_path / "spec.json"
    website_root = tmp_path / "website"
    review_path.write_text(json.dumps(review_package(tmp_path)), encoding="utf-8")
    spec_path.write_text(json.dumps(companion_spec()), encoding="utf-8")

    package = build_website_companion_package(
        review_package_path=review_path,
        companion_spec_path=spec_path,
        website_root=website_root,
        run_generator=False,
    )

    assert package.candidate_id == "erf-018-fake-reviews"
    assert package.page_payload_json.exists()
    assert package.update_allowed is False
    assert package.website_payload_sha256
