"""
회귀 테스트: .github/workflows/guard.yml 및 ci.yml의 task_id 추출 regex 검증.

목적: task-N+M 형식(예: task-2472+1)이 task-N 으로 잘리지 않고 전체 매칭되는지 확인.
"""

import re
import os
import pytest

# worktree 기준 경로
_REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
_GUARD_YML = os.path.join(_REPO_ROOT, ".github", "workflows", "guard.yml")
_CI_YML = os.path.join(_REPO_ROOT, ".github", "workflows", "ci.yml")

# 테스트 케이스: (입력 문자열, 기대 매칭값)
TEST_CASES = [
    ("task/task-2472-dev1",   "task-2472"),
    ("task/task-2472+1-dev1", "task-2472+1"),
    ("task/task-2467+3-dev2", "task-2467+3"),
    ("task/task-2483-dev3",   "task-2483"),
]


def _extract_ere_patterns(yml_path: str) -> list[str]:
    """
    yml 파일에서 `grep -oE '...'` 형태의 ERE 패턴 문자열을 모두 추출한다.
    단일 따옴표 내의 패턴만 추출 (쉘 스크립트 관행).
    """
    patterns = []
    with open(yml_path, encoding="utf-8") as f:
        for line in f:
            m = re.search(r"grep\s+-oE\s+'([^']+)'", line)
            if m:
                ere = m.group(1)
                # task-id 관련 패턴만 필터
                if "task-" in ere:
                    patterns.append(ere)
    return patterns


def _ere_to_python_pattern(ere: str) -> re.Pattern:
    """
    ERE 패턴을 파이썬 re 모듈용 패턴으로 변환한다.

    ERE에서 백슬래시+플러스는 리터럴 '+' 이고,
    파이썬 re에서도 동일하게 동작하므로 변환 없이 사용 가능.
    """
    return re.compile(ere)


class TestGuardYmlRegex:
    """guard.yml의 task_id 추출 regex 회귀 테스트."""

    def test_patterns_found(self):
        """guard.yml에서 task-id 관련 grep -oE 패턴이 2건 이상 추출되어야 한다."""
        patterns = _extract_ere_patterns(_GUARD_YML)
        assert len(patterns) >= 2, (
            f"guard.yml에서 task-id regex 패턴이 {len(patterns)}건만 추출됨 (최소 2건 필요). "
            f"추출된 패턴: {patterns}"
        )

    @pytest.mark.parametrize("input_str,expected", TEST_CASES)
    def test_regex_matching(self, input_str: str, expected: str):
        """각 입력에 대해 guard.yml의 모든 task-id regex가 기대값을 정확히 매칭해야 한다."""
        patterns = _extract_ere_patterns(_GUARD_YML)
        assert patterns, f"guard.yml에서 추출된 패턴이 없음: {_GUARD_YML}"

        for ere in patterns:
            compiled = _ere_to_python_pattern(ere)
            match = compiled.search(input_str)
            assert match is not None, (
                f"[guard.yml] 패턴 '{ere}'이 입력 '{input_str}'에 매칭 없음"
            )
            actual = match.group(0)
            assert actual == expected, (
                f"[guard.yml] 패턴 '{ere}': 입력='{input_str}', "
                f"기대='{expected}', 실제='{actual}' — 잘림 감지!"
            )


class TestCiYmlRegex:
    """ci.yml의 task_id 추출 regex 회귀 테스트."""

    def test_patterns_found(self):
        """ci.yml에서 task-id 관련 grep -oE 패턴이 4건 이상 추출되어야 한다."""
        patterns = _extract_ere_patterns(_CI_YML)
        assert len(patterns) >= 4, (
            f"ci.yml에서 task-id regex 패턴이 {len(patterns)}건만 추출됨 (최소 4건 필요). "
            f"추출된 패턴: {patterns}"
        )

    @pytest.mark.parametrize("input_str,expected", TEST_CASES)
    def test_regex_matching(self, input_str: str, expected: str):
        """각 입력에 대해 ci.yml의 모든 task-id regex가 기대값을 정확히 매칭해야 한다."""
        patterns = _extract_ere_patterns(_CI_YML)
        assert patterns, f"ci.yml에서 추출된 패턴이 없음: {_CI_YML}"

        for ere in patterns:
            compiled = _ere_to_python_pattern(ere)
            match = compiled.search(input_str)
            assert match is not None, (
                f"[ci.yml] 패턴 '{ere}'이 입력 '{input_str}'에 매칭 없음"
            )
            actual = match.group(0)
            assert actual == expected, (
                f"[ci.yml] 패턴 '{ere}': 입력='{input_str}', "
                f"기대='{expected}', 실제='{actual}' — 잘림 감지!"
            )


class TestTotalPatternCount:
    """두 파일 합산 패턴 수가 6건 이상인지 검증 (누락 방지)."""

    def test_total_patterns_at_least_6(self):
        guard_patterns = _extract_ere_patterns(_GUARD_YML)
        ci_patterns = _extract_ere_patterns(_CI_YML)
        total = len(guard_patterns) + len(ci_patterns)
        assert total >= 6, (
            f"전체 패턴 수 {total}건 (guard={len(guard_patterns)}, ci={len(ci_patterns)}). "
            f"최소 6건 필요. 누락 가능성 점검 요."
        )
