"""修复管线断点续跑 progress 管理测试。"""
from __future__ import annotations

import asyncio
import json

import pytest


def test_load_progress_missing_file(tmp_path):
    """progress 文件不存在时返回空集合。"""
    from tools.repair_trees import load_progress
    result = load_progress(tmp_path / "nonexistent.json")
    assert result == set()


def test_load_progress_valid_file(tmp_path):
    """正常读取已有 progress 文件。"""
    from tools.repair_trees import load_progress
    path = tmp_path / "progress.json"
    path.write_text(json.dumps({"finished_video_ids": ["vid_a", "vid_b"]}))
    result = load_progress(path)
    assert result == {"vid_a", "vid_b"}


def test_load_progress_corrupted_file(tmp_path):
    """损坏的 JSON 文件返回空集合（不抛异常）。"""
    from tools.repair_trees import load_progress
    path = tmp_path / "progress.json"
    path.write_text("{invalid json")
    result = load_progress(path)
    assert result == set()


@pytest.mark.asyncio
async def test_save_progress_atomic(tmp_path):
    """save_progress 原子写入，并发调用不丢失更新。"""
    from tools.repair_trees import save_progress
    path = tmp_path / "progress.json"
    lock = asyncio.Lock()
    await save_progress(path, lock, "vid_a")
    await save_progress(path, lock, "vid_b")
    data = json.loads(path.read_text())
    assert set(data["finished_video_ids"]) == {"vid_a", "vid_b"}


@pytest.mark.asyncio
async def test_save_progress_concurrent(tmp_path):
    """16 路并发 save_progress 不丢失更新。"""
    from tools.repair_trees import save_progress
    path = tmp_path / "progress.json"
    lock = asyncio.Lock()
    tasks = [save_progress(path, lock, f"vid_{i}") for i in range(16)]
    await asyncio.gather(*tasks)
    data = json.loads(path.read_text())
    assert len(data["finished_video_ids"]) == 16


def test_should_skip_finished():
    """已在 finished 集合中的视频应跳过。"""
    from tools.repair_trees import should_skip_video
    finished = {"vid_a", "vid_b"}
    assert should_skip_video("vid_a", finished, reaggregate_all=False) is True
    assert should_skip_video("vid_c", finished, reaggregate_all=False) is False


def test_should_skip_reaggregate_all_forces_rerun():
    """--reaggregate-all 标志强制不跳过。"""
    from tools.repair_trees import should_skip_video
    finished = {"vid_a"}
    assert should_skip_video("vid_a", finished, reaggregate_all=True) is False
