"""
test_dispatch_routing.py

dispatch.py 논리적 팀 라우팅 기능 단위 테스트 (토트 작성)

테스트 항목:
- _load_logical_teams(): config/constants.json에서 logical_teams 도메인 매핑 로드
- _suggest_team(): 키워드 매칭으로 적합한 논리적 팀 추천
- _validate_team_routing(): dev팀에 논리적 팀 소관 작업 위임 시 경고 반환
"""

import json
import os
import sys
import types
from pathlib import Path

import pytest

# ---------------------------------------------------------------------------
# 헬퍼: dispatch 모듈을 격리된 WORKSPACE로 재로드
# ---------------------------------------------------------------------------


def _load_dispatch_with_workspace(tmp_path: Path) -> types.ModuleType:
    """dispatch 모듈을 tmp_path를 WORKSPACE로 설정하여 로드한다."""
    workspace = Path(os.environ.get("WORKSPACE_ROOT", "/home/jay/workspace"))
    if str(workspace) not in sys.path:
        sys.path.insert(0, str(workspace))

    import prompts.team_prompts  # noqa: F401

    for mod_name in list(sys.modules.keys()):
        if mod_name == "dispatch":
            del sys.modules[mod_name]

    import dispatch as _dispatch

    _dispatch.WORKSPACE = tmp_path
    return _dispatch


# ---------------------------------------------------------------------------
# fixture
# ---------------------------------------------------------------------------


@pytest.fixture()
def dispatch_mod(tmp_path):
    """격리된 WORKSPACE를 사용하는 dispatch 모듈 반환"""
    (tmp_path / "memory").mkdir(parents=True, exist_ok=True)
    (tmp_path / "memory" / "tasks").mkdir(parents=True, exist_ok=True)
    return _load_dispatch_with_workspace(tmp_path)


# ---------------------------------------------------------------------------
# Class 1: TestSuggestTeam
# ---------------------------------------------------------------------------


class TestSuggestTeam:
    """_suggest_team() 키워드 매칭 정확도 검증"""

    def test_design_keywords_suggest_design(self, dispatch_mod):
        """디자인 키워드 → design 팀 추천"""
        result = dispatch_mod._suggest_team("배너 디자인 제작")
        assert result == "design"

    def test_marketing_keywords_suggest_marketing(self, dispatch_mod):
        """마케팅 키워드 → marketing 팀 추천"""
        result = dispatch_mod._suggest_team("SEO 콘텐츠 전략 수립")
        assert result == "marketing"

    def test_content_keywords_suggest_content(self, dispatch_mod):
        """콘텐츠 키워드 → content 팀 추천"""
        result = dispatch_mod._suggest_team("블로그 작성 및 포스팅 작성")
        assert result == "content"

    def test_publishing_keywords_suggest_publishing(self, dispatch_mod):
        """퍼블리싱 키워드 → publishing 팀 추천"""
        result = dispatch_mod._suggest_team("블로그 발행 업로드")
        assert result == "publishing"

    def test_no_match_returns_none(self, dispatch_mod):
        """매칭 키워드 없으면 None 반환"""
        result = dispatch_mod._suggest_team("dispatch.py 버그 수정")
        assert result is None

    def test_anti_keywords_exclude_design(self, dispatch_mod):
        """design anti-keyword 포함 시 design 추천 제외"""
        # "이미지"는 design 키워드이지만 "HTML 수정"은 anti-keyword
        result = dispatch_mod._suggest_team("이미지 렌더러 HTML 수정")
        assert result != "design"

    def test_highest_score_wins(self, dispatch_mod):
        """여러 팀이 매칭될 때 가장 높은 점수의 팀 추천"""
        # "디자인 이미지 시안 비주얼" → design 4점 vs marketing 0점
        result = dispatch_mod._suggest_team("디자인 이미지 시안 비주얼 제작")
        assert result == "design"

    def test_empty_task_desc_returns_none(self, dispatch_mod):
        """빈 작업 설명은 None 반환"""
        result = dispatch_mod._suggest_team("")
        assert result is None


# ---------------------------------------------------------------------------
# Class 2: TestValidateTeamRouting
# ---------------------------------------------------------------------------


class TestValidateTeamRouting:
    """_validate_team_routing() 라우팅 검증 정확도 검증"""

    def test_dev_team_with_design_task_returns_warning(self, dispatch_mod):
        """dev팀에 디자인 작업 → 경고 메시지 반환"""
        result = dispatch_mod._validate_team_routing("dev1-team", "배너 디자인 제작")
        assert result is not None
        assert "design" in result
        assert "--override-routing" in result

    def test_dev_team_with_coding_task_returns_none(self, dispatch_mod):
        """dev팀에 코딩 작업 → 경고 없음"""
        result = dispatch_mod._validate_team_routing("dev1-team", "dispatch.py 버그 수정")
        assert result is None

    def test_logical_team_returns_none(self, dispatch_mod):
        """논리적 팀(design)에 디자인 작업 → 경고 없음"""
        result = dispatch_mod._validate_team_routing("design", "배너 디자인 제작")
        assert result is None

    def test_override_routing_bypasses_warning(self, dispatch_mod):
        """override_routing=True → 경고 우회"""
        result = dispatch_mod._validate_team_routing("dev1-team", "배너 디자인 제작", override_routing=True)
        assert result is None

    def test_marketing_team_no_self_warning(self, dispatch_mod):
        """marketing 팀에 마케팅 작업 → 자기 자신이므로 경고 없음"""
        result = dispatch_mod._validate_team_routing("marketing", "마케팅 전략 수립")
        assert result is None


# ---------------------------------------------------------------------------
# Class 3: TestLoadLogicalTeams
# ---------------------------------------------------------------------------


class TestLoadLogicalTeams:
    """_load_logical_teams() 도메인 매핑 로드 검증"""

    def test_returns_dict(self, dispatch_mod):
        """반환값이 dict 타입"""
        result = dispatch_mod._load_logical_teams()
        assert isinstance(result, dict)

    def test_has_design_team(self, dispatch_mod):
        """design 팀 존재"""
        result = dispatch_mod._load_logical_teams()
        assert "design" in result

    def test_design_has_keywords(self, dispatch_mod):
        """design 팀에 keywords 존재"""
        result = dispatch_mod._load_logical_teams()
        assert "keywords" in result["design"]
        assert len(result["design"]["keywords"]) > 0

    def test_design_has_anti_keywords(self, dispatch_mod):
        """design 팀에 anti_keywords 존재"""
        result = dispatch_mod._load_logical_teams()
        assert "anti_keywords" in result["design"]
        assert len(result["design"]["anti_keywords"]) > 0

    def test_fallback_when_config_unavailable(self, dispatch_mod, tmp_path):
        """ConfigManager 불가 시 파일 직접 읽기 fallback"""
        # config 디렉토리에 constants.json 생성
        config_dir = tmp_path / "config"
        config_dir.mkdir(exist_ok=True)
        test_data = {
            "logical_teams": {
                "test_team": {
                    "keywords": ["test"],
                    "anti_keywords": [],
                    "description": "test",
                }
            }
        }
        (config_dir / "constants.json").write_text(json.dumps(test_data), encoding="utf-8")

        # _CONFIG_AVAILABLE를 False로 모킹
        original = dispatch_mod._CONFIG_AVAILABLE
        dispatch_mod._CONFIG_AVAILABLE = False
        try:
            result = dispatch_mod._load_logical_teams()
            assert "test_team" in result
        finally:
            dispatch_mod._CONFIG_AVAILABLE = original
