#!/usr/bin/env python3
"""
Task 115-1 테스트: 팀장 가이드 분리 및 프롬프트 크기 게이트

대상:
  1. team_prompts.py의 build_prompt() 변경:
     - 가이드 텍스트(작업 철학, 실패 시나리오, 셀프QC)를 파일 참조로 분리
     - teamlead-guide.md 경로 반환 확인
     - 기존 가이드 텍스트가 직접 포함되지 않는지 확인
     - level별 분기 동작 확인 (normal은 셀프QC만, critical은 마아트 추가, security는 로키 추가)

  2. dispatch.py의 dispatch() 함수 변경:
     - 프롬프트 크기 검증 게이트 추가
     - 직접 호출은 하지 않고, 소스 코드와 build_prompt 길이로 간접 검증

실행:
    pytest /home/jay/workspace/teams/dev1/test_task_115_1.py -v
"""

import sys
sys.path.insert(0, "/home/jay/workspace")

import pytest
from pathlib import Path
from prompts.team_prompts import build_prompt, TEAMLEAD_GUIDE_PATH


GUIDE_PATH = Path(TEAMLEAD_GUIDE_PATH)


class TestTeamleadGuideSeparation:
    """팀장 가이드 분리 및 파일 참조 테스트"""

    def test_guide_file_exists(self):
        """teamlead-guide.md 파일이 존재하는지 확인"""
        assert GUIDE_PATH.exists(), f"팀장 가이드 파일이 없음: {GUIDE_PATH}"

    def test_guide_file_content_includes_core_texts(self):
        """teamlead-guide.md에 핵심 텍스트가 포함되어 있는지 확인"""
        guide_text = GUIDE_PATH.read_text(encoding="utf-8")

        # 핵심 텍스트 확인
        core_texts = [
            "계획 우선 원칙",
            "비정상 입력",
            "스스로 점검",
            "마아트",
            "로키",
        ]

        for text in core_texts:
            assert text in guide_text, f"가이드에 '{text}' 포함 필수, 실제 내용 일부: {guide_text[:200]}"

    def test_build_prompt_includes_guide_path(self):
        """build_prompt() 반환값에 teamlead-guide.md 경로 참조가 포함되어야 함"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="normal")

        # 경로가 포함되어 있는지 확인
        assert TEAMLEAD_GUIDE_PATH in prompt, \
            f"프롬프트에 가이드 경로({TEAMLEAD_GUIDE_PATH})가 포함되어야 함"

    def test_build_prompt_does_not_include_direct_guide_texts_normal(self):
        """normal 레벨: 기존 가이드 텍스트가 직접 포함되지 않는지 확인"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="normal")

        # 기존에 직접 포함되던 긴 가이드 텍스트는 없어야 함
        # (단, "계획 우선" 같은 짧은 문구는 파일 참조 관련해서 나올 수 있으므로,
        #  명확히 다른 맥락의 텍스트로 확인)
        unwanted_patterns = [
            "계획 우선 원칙\n- 코딩 전 작업을 분석",  # 매뉴얼 스타일 나열
            "비정상 입력/상태\n- 이 기능의 입력이",  # 매뉴얼 스타일 나열
        ]
        for pattern in unwanted_patterns:
            assert pattern not in prompt, \
                f"프롬프트에 직접 가이드 텍스트가 포함되면 안 됨: {pattern[:50]}"

    def test_build_prompt_normal_includes_selfqc_reference(self):
        """normal 레벨: 셀프QC 파일 참조만 포함"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="normal")

        # 셀프QC 섹션이 파일 참조로 있어야 함
        assert "셀프 QC" in prompt, "normal 레벨에 '셀프 QC' 문구가 있어야 함"
        assert TEAMLEAD_GUIDE_PATH in prompt, "셀프QC 섹션에서 가이드 파일 참조"

    def test_build_prompt_critical_includes_maat_reference(self):
        """critical 레벨: 셀프QC + 마아트 참조 포함"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="critical")

        # 셀프QC + 마아트 파일 참조
        assert "셀프 QC" in prompt, "critical 레벨에 '셀프 QC' 문구가 있어야 함"
        assert "마아트" in prompt, "critical 레벨에 '마아트' 문구가 있어야 함"
        assert TEAMLEAD_GUIDE_PATH in prompt, "critical 레벨에서 가이드 파일 참조"

    def test_build_prompt_security_includes_loki_reference(self):
        """security 레벨: 셀프QC + 마아트 + 로키 참조 포함"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="security")

        # 셀프QC + 마아트 + 로키 파일 참조
        assert "셀프 QC" in prompt, "security 레벨에 '셀프 QC' 문구가 있어야 함"
        assert "마아트" in prompt, "security 레벨에 '마아트' 문구가 있어야 함"
        assert "로키" in prompt, "security 레벨에 '로키' 문구가 있어야 함"
        assert TEAMLEAD_GUIDE_PATH in prompt, "security 레벨에서 가이드 파일 참조"

    def test_build_prompt_level_branching_consistency(self):
        """level별 분기 동작이 명확히 구분되는지 확인"""
        normal_prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="normal")
        critical_prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="critical")
        security_prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="security")

        # normal에는 마아트/로키가 없어야 함
        assert "마아트" not in normal_prompt, "normal 레벨에는 마아트 참조가 없어야 함"
        assert "로키" not in normal_prompt, "normal 레벨에는 로키 참조가 없어야 함"

        # critical에는 마아트는 있지만 로키는 없어야 함
        assert "마아트" in critical_prompt, "critical 레벨에는 마아트 참조가 있어야 함"
        assert "로키" not in critical_prompt, "critical 레벨에는 로키 참조가 없어야 함"

        # security에는 둘 다 있어야 함
        assert "마아트" in security_prompt, "security 레벨에는 마아트 참조가 있어야 함"
        assert "로키" in security_prompt, "security 레벨에는 로키 참조가 있어야 함"


class TestPromptSizeGate:
    """프롬프트 크기 게이트 테스트"""

    def test_dispatch_py_contains_size_gate_code(self):
        """dispatch.py에 프롬프트 크기 검증 게이트 코드가 있는지 확인"""
        dispatch_file = Path("/home/jay/workspace/dispatch.py")
        assert dispatch_file.exists(), "dispatch.py 파일이 없음"

        dispatch_text = dispatch_file.read_text(encoding="utf-8")

        # 게이트 관련 키 문자열 확인
        gate_patterns = [
            "프롬프트가",  # 로그 메시지 시작
            "자입니다",    # 로그 메시지 끝
            "3000",       # 3000자 제한
        ]

        for pattern in gate_patterns:
            assert pattern in dispatch_text, \
                f"dispatch.py에 '{pattern}' 문자열이 있어야 함 (크기 게이트 코드)"

    def test_build_prompt_returns_reasonable_length_normal(self):
        """normal 레벨 프롬프트 길이가 합리적 범위인지 확인"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="normal")

        prompt_len = len(prompt)
        # 파일 참조 분리 후 프롬프트는 3000자 이하여야 함
        assert prompt_len > 500, f"프롬프트가 너무 짧음: {prompt_len}자"
        assert prompt_len < 3000, f"프롬프트가 3000자 초과: {prompt_len}자"

    def test_build_prompt_returns_reasonable_length_critical(self):
        """critical 레벨 프롬프트 길이가 합리적 범위인지 확인"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="critical")

        prompt_len = len(prompt)
        # critical은 마아트 참조가 추가되지만, 여전히 3000자 이하여야 함
        assert prompt_len > 500, f"프롬프트가 너무 짧음: {prompt_len}자"
        assert prompt_len < 3000, f"프롬프트가 3000자 초과: {prompt_len}자"

    def test_build_prompt_returns_reasonable_length_security(self):
        """security 레벨 프롬프트 길이가 합리적 범위인지 확인"""
        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="security")

        prompt_len = len(prompt)
        # security는 로키 참조도 추가되지만, 게이트는 3000~3100 범위 내 허용
        # (가이드 분리로 인해 기존보다 훨씬 짧아짐)
        assert prompt_len > 500, f"프롬프트가 너무 짧음: {prompt_len}자"
        assert prompt_len < 3100, f"프롬프트가 3100자 초과: {prompt_len}자"

    def test_prompt_length_reduced_after_guide_separation(self):
        """가이드 분리로 인해 프롬프트 길이가 줄었는지 간접 검증"""
        # 간접 검증: build_prompt가 teamlead-guide.md 경로 참조를 사용하므로,
        # 파일에 직접 포함된 긴 가이드 텍스트 대비 짧아야 함

        prompt = build_prompt("dev1-team", "task-test-1", "테스트 작업", level="normal")

        # 핵심: 파일 참조는 포함되지만, 실제 가이드 내용은 포함되지 않음
        # 따라서 프롬프트 길이는 관리 가능한 수준
        assert len(prompt) < 3000, "가이드 분리 후 프롬프트는 3000자 미만이어야 함"

        # 파일 참조가 있으므로 최소 길이는 보장
        assert TEAMLEAD_GUIDE_PATH in prompt, "가이드 파일 참조가 포함되어야 함"


class TestIntegration:
    """통합 테스트"""

    def test_all_team_levels_produce_valid_prompts(self):
        """모든 팀과 레벨 조합에서 유효한 프롬프트를 생성하는지 확인"""
        teams = ["dev1-team", "dev2-team", "dev3-team"]
        levels = ["normal", "critical", "security"]

        for team_id in teams:
            for level in levels:
                prompt = build_prompt(team_id, "task-integration-1", "통합 테스트 작업", level=level)

                # 프롬프트가 비어있지 않고, 가이드 참조가 있어야 함
                assert prompt, f"{team_id}/{level}: 프롬프트가 비어있음"
                assert TEAMLEAD_GUIDE_PATH in prompt, \
                    f"{team_id}/{level}: 가이드 파일 참조가 없음"
                assert len(prompt) > 500, \
                    f"{team_id}/{level}: 프롬프트가 너무 짧음 ({len(prompt)}자)"
                # 게이트는 3000자를 기준으로 하지만, 팀/레벨별 약간의 변동성 허용 (3200자 이하)
                # dev3-team의 워크플로우가 더 길기 때문에 안정적 범위로 설정
                assert len(prompt) < 3200, \
                    f"{team_id}/{level}: 프롬프트가 3200자 초과 ({len(prompt)}자)"


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
