"""tests/regression/test_dispatch_hardening_2487.py — task-2487 회귀 테스트 (Group A).

dispatch 영역에서 V2 task ID 패턴이 정상 인식되는지 검증한다.
dispatch.__init__ 는 대형 모듈(73k 토큰)이므로 직접 import 하지 않고:
  1. utils.task_id_parser.is_valid_task_id V2 인식 검증
  2. dispatch/__init__.py 소스에 is_valid_task_id 호출이 존재하는지 메타 테스트

헤임달(개발2팀 테스터) 작성 / task-2487.
"""
from __future__ import annotations

import importlib.util
import sys
from pathlib import Path

WORKSPACE = Path(__file__).resolve().parents[2]


def _load_module(mod_name: str, file_rel: str):
    file_path = WORKSPACE / file_rel
    spec = importlib.util.spec_from_file_location(mod_name, str(file_path))
    if spec is None or spec.loader is None:
        raise ImportError(f"cannot load spec for {file_path}")
    module = importlib.util.module_from_spec(spec)
    sys.modules[mod_name] = module
    spec.loader.exec_module(module)
    return module


tip = _load_module("tip_2487_dispatch", "utils/task_id_parser.py")


# ---------------------------------------------------------------------------
# A-1: is_valid_task_id — V2 패턴 통과 검증
# ---------------------------------------------------------------------------


def test_dispatch_valid_base():
    """단순 base ID task-1234가 V2 패턴으로 valid 인식된다."""
    assert tip.is_valid_task_id("task-1234") is True


def test_dispatch_valid_retry():
    """retry suffix task-1234+1이 V2 패턴으로 valid 인식된다."""
    assert tip.is_valid_task_id("task-1234+1") is True


def test_dispatch_valid_phase():
    """phase suffix task-1234_1.2가 V2 패턴으로 valid 인식된다."""
    assert tip.is_valid_task_id("task-1234_1.2") is True


def test_dispatch_valid_parallel_retry():
    """phase+parallel+retry 전체 조합 task-1234_1.2_a+3이 V2로 valid 인식된다."""
    assert tip.is_valid_task_id("task-1234_1.2_a+3") is True


# ---------------------------------------------------------------------------
# A-2: is_valid_task_id — invalid 거부 검증
# ---------------------------------------------------------------------------


def test_dispatch_invalid_no_prefix():
    """task- 접두사 없는 문자열은 invalid로 거부된다."""
    assert tip.is_valid_task_id("1234") is False


def test_dispatch_invalid_wrong_prefix():
    """잘못된 접두사 문자열은 invalid로 거부된다."""
    assert tip.is_valid_task_id("not-a-task") is False


def test_dispatch_invalid_alpha_num():
    """task-abc 처럼 숫자 아닌 ID는 invalid로 거부된다."""
    assert tip.is_valid_task_id("task-abc") is False


def test_dispatch_invalid_empty():
    """빈 문자열은 invalid로 거부된다."""
    assert tip.is_valid_task_id("") is False


# ---------------------------------------------------------------------------
# A-3: 메타 테스트 — dispatch/__init__.py 소스 내 is_valid_task_id 호출 존재
# ---------------------------------------------------------------------------


def test_dispatch_source_calls_is_valid_task_id():
    """dispatch/__init__.py 소스에 is_valid_task_id 호출이 존재해야 한다."""
    src = (WORKSPACE / "dispatch" / "__init__.py").read_text(encoding="utf-8")
    assert "is_valid_task_id" in src, (
        "dispatch/__init__.py에 is_valid_task_id 호출이 없음 — V2 검증 미적용 가능성"
    )


def test_dispatch_source_imports_task_id_parser():
    """dispatch/__init__.py가 utils.task_id_parser를 import한다."""
    src = (WORKSPACE / "dispatch" / "__init__.py").read_text(encoding="utf-8")
    assert "task_id_parser" in src, (
        "dispatch/__init__.py에 utils.task_id_parser import가 없음"
    )


# ---------------------------------------------------------------------------
# A-4: parse_task_id_v2 — dispatch가 의존하는 분해 함수 동작 검증
# ---------------------------------------------------------------------------


def test_dispatch_parse_base_only():
    """task-1234 파싱 시 base만 채워지고 나머지는 None이다."""
    out = tip.parse_task_id_v2("task-1234")
    assert out["base"] == "task-1234"
    assert out["phase"] is None
    assert out["parallel"] is None
    assert out["retry"] is None


def test_dispatch_parse_retry_suffix():
    """task-1234+1 파싱 시 retry 필드가 +1로 채워진다."""
    out = tip.parse_task_id_v2("task-1234+1")
    assert out == {"base": "task-1234", "phase": None, "parallel": None, "retry": "+1"}


def test_dispatch_parse_phase_suffix():
    """task-1234_1.2 파싱 시 phase 필드가 _1.2로 채워진다."""
    out = tip.parse_task_id_v2("task-1234_1.2")
    assert out == {"base": "task-1234", "phase": "_1.2", "parallel": None, "retry": None}


def test_dispatch_parse_full_combo():
    """task-1234_1.2_a+3 파싱 시 4개 필드 모두 채워진다."""
    out = tip.parse_task_id_v2("task-1234_1.2_a+3")
    assert out == {
        "base": "task-1234",
        "phase": "_1.2",
        "parallel": "_a",
        "retry": "+3",
    }
