"""
test_dispatch_counter_sync.py

dispatch.py의 task-counter 정합성 개선에 대한 테스트:
  1. generate_task_id() — 카운터 < timers 최대값 → 보정
  2. generate_task_id() — 카운터 >= timers 최대값 → 보정 없음
  3. _sync_counter_if_needed() — 외부 ID가 카운터보다 큰 경우
  4. _sync_counter_if_needed() — 외부 ID가 카운터보다 작은 경우
  5. _sync_counter_if_needed() — 잘못된 task_id 형식 → 무시
"""

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

# dispatch.py가 있는 workspace를 sys.path에 추가
sys.path.insert(0, "/home/jay/workspace")

import dispatch  # noqa: E402

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _make_timers(tmp_path: Path, task_ids: list[str]) -> None:
    """task-timers.json을 tmp_path/memory/ 에 생성."""
    memory = tmp_path / "memory"
    memory.mkdir(parents=True, exist_ok=True)
    tasks = {tid: {"status": "done"} for tid in task_ids}
    data = {"tasks": tasks}
    (memory / "task-timers.json").write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")


def _make_counter(tmp_path: Path, value: int) -> None:
    """task-counter 파일을 tmp_path/memory/ 에 생성."""
    memory = tmp_path / "memory"
    memory.mkdir(parents=True, exist_ok=True)
    (memory / ".task-counter").write_text(str(value), encoding="utf-8")


def _read_counter(tmp_path: Path) -> int:
    return int((tmp_path / "memory" / ".task-counter").read_text().strip())


# ---------------------------------------------------------------------------
# Test 1: generate_task_id() — 카운터 < timers 최대 → 보정
# ---------------------------------------------------------------------------


def test_generate_task_id_counter_less_than_timers(tmp_path):
    """카운터(100)가 timers 최대(200)보다 작으면 timers 최대+1(201)로 보정되어 task-201 생성."""
    _make_counter(tmp_path, 100)
    _make_timers(tmp_path, ["task-200.1"])

    with patch.object(dispatch, "WORKSPACE", tmp_path):
        task_id = dispatch.generate_task_id()

    assert task_id == "task-201", f"Expected task-201, got {task_id}"
    # 카운터는 202로 증가되어 있어야 함
    assert _read_counter(tmp_path) == 202, f"Expected counter=202, got {_read_counter(tmp_path)}"


# ---------------------------------------------------------------------------
# Test 2: generate_task_id() — 카운터 >= timers 최대 → 보정 없음
# ---------------------------------------------------------------------------


def test_generate_task_id_counter_greater_than_timers(tmp_path):
    """카운터(300)가 timers 최대(200)보다 크면 카운터 값(300) 그대로 사용해 task-300 생성."""
    _make_counter(tmp_path, 300)
    _make_timers(tmp_path, ["task-200.1"])

    with patch.object(dispatch, "WORKSPACE", tmp_path):
        task_id = dispatch.generate_task_id()

    assert task_id == "task-300", f"Expected task-300, got {task_id}"
    # 카운터는 301로 증가되어 있어야 함
    assert _read_counter(tmp_path) == 301, f"Expected counter=301, got {_read_counter(tmp_path)}"


# ---------------------------------------------------------------------------
# Test 3: _sync_counter_if_needed() — 외부 ID > 카운터 → 카운터 업데이트
# ---------------------------------------------------------------------------


def test_sync_counter_if_needed_external_larger(tmp_path):
    """카운터(100)보다 큰 task-1280.1 지정 시 카운터가 1281로 업데이트된다."""
    (tmp_path / "memory").mkdir(parents=True, exist_ok=True)
    _make_counter(tmp_path, 100)
    with patch.object(dispatch, "WORKSPACE", tmp_path):
        dispatch._sync_counter_if_needed("task-1280.1")

    assert _read_counter(tmp_path) == 1281, f"Expected counter=1281, got {_read_counter(tmp_path)}"


# ---------------------------------------------------------------------------
# Test 4: _sync_counter_if_needed() — 외부 ID < 카운터 → 카운터 변경 없음
# ---------------------------------------------------------------------------


def test_sync_counter_if_needed_external_smaller(tmp_path):
    """카운터(1300)보다 작은 task-1200.1 지정 시 카운터는 변하지 않는다."""
    (tmp_path / "memory").mkdir(parents=True, exist_ok=True)
    _make_counter(tmp_path, 1300)

    with patch.object(dispatch, "WORKSPACE", tmp_path):
        dispatch._sync_counter_if_needed("task-1200.1")

    assert _read_counter(tmp_path) == 1300, f"Expected counter=1300 (unchanged), got {_read_counter(tmp_path)}"


# ---------------------------------------------------------------------------
# Test 5: _sync_counter_if_needed() — 잘못된 task_id 형식 → 예외 없이 무시
# ---------------------------------------------------------------------------


def test_sync_counter_if_needed_invalid_format(tmp_path):
    """'invalid-id' 같은 잘못된 형식은 예외 없이 무시하며 카운터도 변경하지 않는다."""
    (tmp_path / "memory").mkdir(parents=True, exist_ok=True)
    _make_counter(tmp_path, 500)

    with patch.object(dispatch, "WORKSPACE", tmp_path):
        # 예외가 발생하지 않아야 함
        dispatch._sync_counter_if_needed("invalid-id")

    assert _read_counter(tmp_path) == 500, f"Expected counter=500 (unchanged), got {_read_counter(tmp_path)}"
