"""媒体落盘离线测试：注入假 downloader，断言图片落盘 + card.url 改写为 /data 路径。"""
from __future__ import annotations

from creation_knowledge import media
from core.models import Card, Post

PNG = b"\x89PNG\r\n\x1a\n" + b"fakepng"
JPG = b"\xff\xd8\xff\xe0" + b"fakejpg"


def _post():
    return Post(
        id="xhs_1", platform="xiaohongshu", url="u", content_id="1",
        image_urls=["http://cdn/a", "http://cdn/b"],
        cards=[Card(index=1, kind="image", url="http://cdn/a"),
               Card(index=2, kind="image", url="http://cdn/b")],
    )


def test_media_target():
    t = media.media_target("data", "20260616-101010", "douyin", "dy_9")
    assert str(t.dir).endswith("data/20260616-101010/douyin/dy_9")
    assert t.public_base == "/data/20260616-101010/douyin/dy_9"


def test_save_images_writes_and_rewrites(tmp_path):
    bodies = {"http://cdn/a": PNG, "http://cdn/b": JPG}
    calls = []

    def dl(url, platform):
        calls.append((url, platform))
        return bodies[url]

    post = _post()
    media.save_images(post, tmp_path, "/data/B/xiaohongshu/xhs_1", downloader=dl)

    assert (tmp_path / "image_1.png").read_bytes() == PNG  # 文件头嗅探出 .png
    assert (tmp_path / "image_2.jpg").read_bytes() == JPG
    assert post.cards[0].url == "/data/B/xiaohongshu/xhs_1/image_1.png"
    assert post.cards[1].url == "/data/B/xiaohongshu/xhs_1/image_2.jpg"
    assert calls == [("http://cdn/a", "xiaohongshu"), ("http://cdn/b", "xiaohongshu")]


def test_save_images_skips_failures(tmp_path):
    """单张下载失败只跳过，不抛、不改这张卡 url。"""
    def dl(url, platform):
        if url.endswith("b"):
            raise RuntimeError("boom")
        return JPG

    post = _post()
    media.save_images(post, tmp_path, "/data/B/xiaohongshu/xhs_1", downloader=dl)

    assert post.cards[0].url == "/data/B/xiaohongshu/xhs_1/image_1.jpg"
    assert post.cards[1].url == "http://cdn/b"  # 失败的保持原样


def test_save_images_ignores_local_and_segment(tmp_path):
    """已是本地路径 / 非 image 卡不处理。"""
    post = Post(id="x", platform="douyin", url="u", content_id="1",
                cards=[Card(index=1, kind="segment", url="/data/x/video.mp4", start=0, end=3),
                       Card(index=2, kind="image", url="/data/x/image_2.jpg")])

    def dl(url, platform):
        raise AssertionError("不应被调用")

    media.save_images(post, tmp_path, "/data/x", downloader=dl)
    assert post.cards[0].url == "/data/x/video.mp4"
    assert post.cards[1].url == "/data/x/image_2.jpg"
