"""原生整段视频提取离线测试：注入假 http_post 返回 segments，断言段卡 + 内容。"""
from __future__ import annotations

import json

from core.config import PgConfig, Settings
from decode_content.readers.video import extract_video
from core.models import Post

SEGMENTS = json.dumps({
    "video_title": "AI视频教程", "overall": "教 AI 出片",
    "segments": [
        {"start": "00:00", "end": "00:18", "title": "问题与简介",
         "knowledge_types": ["what"], "what": "常见翻车", "why": None, "how": None},
        {"start": "00:19", "end": "00:48", "title": "去噪原理",
         "knowledge_types": ["why"], "what": None, "why": "噪声去噪类似雕刻", "how": None},
    ]}, ensure_ascii=False)


class _Resp:
    def __init__(self, content): self._c = content
    def raise_for_status(self): return None
    def json(self): return {"choices": [{"message": {"content": self._c}}]}


def _settings() -> Settings:
    return Settings(
        pg=PgConfig(host="h", port=5432, user="u", password="p", database="d"),
        aiddit_crawler_base_url="x", crawler_timeout=30,
        openrouter_timeout_seconds=90,
        openrouter_model="google/gemini-3-flash-preview",
        openrouter_base_url="https://openrouter.ai/api/v1", openrouter_api_key="k",
        llm_model="m", max_cards=12,
        frames_dir="runtime/frames", douyin_ratio="540p", data_dir="")


def _fake_post():
    captured = {}

    def post(url, headers=None, json=None, timeout=None):
        captured["url"] = url
        captured["json"] = json
        return _Resp(SEGMENTS)

    return post, captured


def test_video_extract_makes_segment_cards(tmp_path):
    vf = tmp_path / "v.mp4"
    vf.write_bytes(b"\x00\x00\x00\x18ftypmp42fakevideobytes")
    fake, captured = _fake_post()
    post = Post(id="dy_1", platform="douyin", url="u", content_id="1",
                content_type="video", video_urls=["http://x/play?ratio=default"])

    out = extract_video(post, settings=_settings(), http_post=fake, video_path=str(vf))

    # ExtractedContent.cards = 每段一条内容
    assert len(out.cards) == 2
    assert out.cards[0].index == 1 and "问题" in out.cards[0].content
    assert out.is_empty is False and out.text  # overall 进 text

    # post.cards = 段卡，带 start/end（秒）
    assert len(post.cards) == 2
    assert post.cards[0].kind == "segment"
    assert post.cards[0].start == 0.0 and post.cards[1].start == 19.0
    assert post.cards[1].end == 48.0
    assert post.cards[0].url is None  # 段卡默认无图

    # 请求体含 base64 video_url
    parts = captured["json"]["messages"][0]["content"]
    assert any(p["type"] == "video_url"
               and p["video_url"]["url"].startswith("data:video/mp4;base64,")
               for p in parts)


def test_video_extract_saves_and_sets_url(tmp_path):
    """传 save_path/public_url：整段视频落盘 + 段卡 url 指向整段。"""
    vf = tmp_path / "src.mp4"
    vf.write_bytes(b"\x00\x00\x00\x18ftypmp42fakevideobytes")
    save_path = tmp_path / "out" / "video.mp4"
    fake, _ = _fake_post()
    post = Post(id="dy_1", platform="douyin", url="u", content_id="1",
                content_type="video", video_urls=["http://x/play"])

    extract_video(post, settings=_settings(), http_post=fake, video_path=str(vf),
                  save_path=save_path, public_url="/data/B/douyin/dy_1/video.mp4")

    assert save_path.exists() and save_path.read_bytes() == vf.read_bytes()
    assert all(c.url == "/data/B/douyin/dy_1/video.mp4" for c in post.cards)


def test_extract_video_oss_direct_feed():
    """传 oss_video_url：不下载、不 base64，请求体直接用该 http 直链；段卡 url 指向它。"""
    fake, captured = _fake_post()
    downloads = []

    def spy_downloader(url, platform):
        downloads.append(url)
        return b"should-not-be-called"

    post = Post(id="dy_2", platform="douyin", url="u", content_id="2",
                content_type="video", video_urls=["http://cdn/raw.mp4?sig=tmp"])

    out = extract_video(post, settings=_settings(), http_post=fake,
                        downloader=spy_downloader,
                        oss_video_url="https://res.cybertogether.net/crawler/video/x.mp4")

    assert downloads == []  # 未触发任何下载
    parts = captured["json"]["messages"][0]["content"]
    vparts = [p for p in parts if p["type"] == "video_url"]
    assert vparts and vparts[0]["video_url"]["url"] == "https://res.cybertogether.net/crawler/video/x.mp4"
    assert not vparts[0]["video_url"]["url"].startswith("data:")  # 不是 base64
    assert out.cards and len(post.cards) == 2
    assert all(c.url == "https://res.cybertogether.net/crawler/video/x.mp4" for c in post.cards)
