"""#1743 worker 批量重渲判定 + 封面哈希选帧纯函数测试。

- should_rerender_for_batch_dedup：批次首版查重率 >20% 才重渲（非批次/重渲版/无查重率不重渲）
- pick_batch_cover_index：task_id md5 稳定哈希分散候选帧（同任务稳定、跨任务分散）
"""

from __future__ import annotations

import hashlib
import sys
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[2]
for sub in ("apps/worker", "apps/api", "packages", ""):
    p = str(REPO_ROOT / sub) if sub else str(REPO_ROOT)
    if p not in sys.path:
        sys.path.insert(0, p)

from worker_app.tasks.generation import (  # noqa: E402
    BATCH_RENDER_SIMILARITY_LIMIT,
    pick_batch_cover_index,
    should_rerender_for_batch_dedup,
)


class TestShouldRerenderForBatchDedup:
    def test_non_batch_never_rerenders(self):
        """非批次任务（batch_id 为空）任何查重率都不重渲。"""
        assert should_rerender_for_batch_dedup(batch_id="", render_attempt=0, batch_similarity=0.99) is False
        assert should_rerender_for_batch_dedup(batch_id="", render_attempt=0, batch_similarity=None) is False

    def test_batch_first_version_over_threshold_rerenders(self):
        """批次首版（attempt=0）查重率 >20% → 重渲。"""
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.601) is True
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.21) is True

    def test_batch_first_version_under_threshold_no_rerender(self):
        """批次首版查重率 ≤20% → 不重渲。"""
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.20) is False
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.0) is False
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.05) is False

    def test_rerendered_version_never_rerenders_again(self):
        """重渲版（attempt=1）即使仍超阈值也不再重渲（最多重渲一次）。"""
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=1, batch_similarity=0.99) is False

    def test_missing_similarity_no_rerender(self):
        """查重率缺失（None，非批次查重路径）→ 不重渲。"""
        assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=None) is False

    def test_threshold_constant_is_20_percent(self):
        assert BATCH_RENDER_SIMILARITY_LIMIT == 0.20


class TestPickBatchCoverIndex:
    def test_stable_for_same_task(self):
        """同一 task_id 多次调用结果稳定（重试封面不变）。"""
        first = pick_batch_cover_index("task-abc", 3)
        for _ in range(5):
            assert pick_batch_cover_index("task-abc", 3) == first

    def test_zero_or_one_candidate_returns_zero(self):
        assert pick_batch_cover_index("task-x", 0) == 0
        assert pick_batch_cover_index("task-x", 1) == 0

    def test_index_within_range(self):
        for i in range(20):
            idx = pick_batch_cover_index(f"task-{i}", 3)
            assert 0 <= idx < 3

    def test_matches_md5_formula(self):
        """与主流程公式一致：md5(task_id) % 候选数。"""
        task_id = "task-formula-check"
        expected = int(hashlib.md5(task_id.encode()).hexdigest(), 16) % 3
        assert pick_batch_cover_index(task_id, 3) == expected

    def test_batch_tasks_spread_across_frames(self):
        """30 个批次任务在 3 个候选帧上分散（不能全部落在 frame_0——旧 bug 回归守卫）。"""
        indexes = {pick_batch_cover_index(f"batch-task-{i}", 3) for i in range(30)}
        assert len(indexes) >= 2, f"封面帧应分散到多个帧位，实际全部落在: {indexes}"
