"""low_freq_skip 유틸 단위 테스트."""
from __future__ import annotations

import json
import logging
from pathlib import Path
from unittest.mock import patch

import pytest

from app.core.low_freq_skip import (
    get_skip_file_path,
    load_low_freq_skip_ids,
    save_low_freq_skip_ids,
)


@pytest.fixture
def tmp_projects_dir(tmp_path, monkeypatch):
    """settings.projects_dir을 임시 경로로 패치."""
    from app.core.config import settings as _settings
    monkeypatch.setattr(_settings, "projects_dir", str(tmp_path))
    return tmp_path


def test_get_skip_file_path_structure(tmp_projects_dir):
    path = get_skip_file_path("pid-1", "eid-2")
    expected_tail = Path("pid-1") / "checkpoints" / "images" / "eid-2" / "ref_low_freq_skip.json"
    assert path.as_posix().endswith(expected_tail.as_posix())


def test_load_returns_empty_when_file_missing(tmp_projects_dir):
    assert load_low_freq_skip_ids("pid-x", "eid-x") == set()


def test_save_then_load_round_trip(tmp_projects_dir):
    ids = {"uuid-a", "uuid-b", "uuid-c"}
    save_low_freq_skip_ids("pid-1", "eid-1", ids)
    loaded = load_low_freq_skip_ids("pid-1", "eid-1")
    assert loaded == ids


def test_save_creates_parent_dirs(tmp_projects_dir):
    save_low_freq_skip_ids("new-pid", "new-eid", {"u1"})
    path = get_skip_file_path("new-pid", "new-eid")
    assert path.exists()
    assert path.parent.is_dir()


def test_load_corrupt_json_warns_and_returns_empty(tmp_projects_dir, caplog):
    path = get_skip_file_path("pid-1", "eid-1")
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text("not valid json {", encoding="utf-8")
    with caplog.at_level(logging.WARNING, logger="app.core.low_freq_skip"):
        result = load_low_freq_skip_ids("pid-1", "eid-1")
    assert result == set()
    # 운영자가 JSON 손상을 감지할 수 있어야 함
    assert any("parse failed" in r.message for r in caplog.records)


def test_save_dedupes_input(tmp_projects_dir):
    save_low_freq_skip_ids("pid-1", "eid-1", ["a", "b", "a", "c"])
    loaded = load_low_freq_skip_ids("pid-1", "eid-1")
    assert loaded == {"a", "b", "c"}


def test_save_empty_then_load_empty(tmp_projects_dir):
    save_low_freq_skip_ids("pid-1", "eid-1", [])
    assert load_low_freq_skip_ids("pid-1", "eid-1") == set()


def test_save_and_load_reasoned_report(tmp_path, monkeypatch):
    from app.core import low_freq_skip
    from app.core.config import settings
    monkeypatch.setattr(settings, "projects_dir", str(tmp_path))
    decisions = [
        {"canon_id": "u-a", "skipped": True, "reason": "no required_ref"},
        {"canon_id": "u-b", "skipped": False, "reason": "required_ref present"},
    ]
    low_freq_skip.save_low_freq_skip_report("p1", "e1", decisions)
    assert low_freq_skip.load_low_freq_skip_ids("p1", "e1") == {"u-a"}
    report = low_freq_skip.load_low_freq_skip_report("p1", "e1")
    assert report["version"] == 2
    assert {d["canon_id"] for d in report["decisions"]} == {"u-a", "u-b"}


def test_load_ids_backcompat_with_legacy_array(tmp_path, monkeypatch):
    """구 plain-array 포맷도 load_low_freq_skip_ids 가 계속 읽는다."""
    from app.core import low_freq_skip
    from app.core.config import settings
    monkeypatch.setattr(settings, "projects_dir", str(tmp_path))
    low_freq_skip.save_low_freq_skip_ids("p1", "e1", ["u-x", "u-y"])
    assert low_freq_skip.load_low_freq_skip_ids("p1", "e1") == {"u-x", "u-y"}
