#!/usr/bin/env python3
"""
dry-run 검증 스크립트: .github/workflows/guard.yml 및 ci.yml의
task_id 추출 regex가 task-N+M 형식을 올바르게 매칭하는지 확인한다.

사용법:
    python3 scripts/verify_workflow_taskid_regex.py

모두 PASS면 stdout에 PASS 출력 + exit 0.
잘림 발생 시 stderr에 명확한 메시지 + exit 1.
"""

import re
import os
import sys


# 파일 경로 (스크립트 위치 기준으로 repo root 탐색)
_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
_REPO_ROOT = os.path.dirname(_SCRIPT_DIR)
_GUARD_YML = os.path.join(_REPO_ROOT, ".github", "workflows", "guard.yml")
_CI_YML = os.path.join(_REPO_ROOT, ".github", "workflows", "ci.yml")

# 검증 샘플: (입력, 기대 매칭값)
SAMPLES = [
    ("task-2472+1",       "task-2472+1"),
    ("task-2467+3",       "task-2467+3"),
    ("task-2483",         "task-2483"),
    ("task-2472",         "task-2472"),
    # 브랜치 prefix 포함
    ("task/task-2472+1-dev1", "task-2472+1"),
    ("task/task-2467+3-dev2", "task-2467+3"),
    ("task/task-2483-dev3",   "task-2483"),
    ("task/task-2472-dev1",   "task-2472"),
]


def extract_ere_patterns(yml_path: str) -> list:
    """yml 파일에서 grep -oE '...' 형태의 ERE 패턴(task- 포함)을 추출한다."""
    patterns = []
    with open(yml_path, encoding="utf-8") as f:
        for lineno, line in enumerate(f, 1):
            m = re.search(r"grep\s+-oE\s+'([^']+)'", line)
            if m:
                ere = m.group(1)
                if "task-" in ere:
                    patterns.append((lineno, ere))
    return patterns


def verify_file(label: str, yml_path: str, min_patterns: int) -> list:
    """
    yml 파일의 패턴들에 대해 전체 샘플을 검증한다.
    실패 목록을 반환하고, 실패 시 stderr에 메시지를 출력한다.
    """
    failures = []

    if not os.path.exists(yml_path):
        msg = f"[FAIL] {label}: 파일 미존재 — {yml_path}"
        print(msg, file=sys.stderr)
        failures.append(msg)
        return failures

    patterns = extract_ere_patterns(yml_path)
    print(f"[{label}] 추출된 패턴 {len(patterns)}건:", file=sys.stdout)
    for lineno, ere in patterns:
        print(f"  line {lineno}: {ere}", file=sys.stdout)

    if len(patterns) < min_patterns:
        msg = (
            f"[FAIL] {label}: 패턴이 {len(patterns)}건 — 최소 {min_patterns}건 필요. "
            f"수정 누락 의심."
        )
        print(msg, file=sys.stderr)
        failures.append(msg)
        return failures

    for lineno, ere in patterns:
        compiled = re.compile(ere)
        for input_str, expected in SAMPLES:
            match = compiled.search(input_str)
            if match is None:
                msg = (
                    f"[FAIL] {label} line {lineno} | 패턴='{ere}' | "
                    f"입력='{input_str}' → 매칭 없음 (기대: '{expected}')"
                )
                print(msg, file=sys.stderr)
                failures.append(msg)
            else:
                actual = match.group(0)
                if actual != expected:
                    msg = (
                        f"[FAIL] {label} line {lineno} | 패턴='{ere}' | "
                        f"입력='{input_str}' → 실제='{actual}', 기대='{expected}' "
                        f"— 잘림(truncation) 감지!"
                    )
                    print(msg, file=sys.stderr)
                    failures.append(msg)
                else:
                    print(
                        f"  PASS  line {lineno} | '{input_str}' → '{actual}'",
                        file=sys.stdout,
                    )

    return failures


if __name__ == "__main__":
    all_failures = []

    print("=" * 60)
    print("guard.yml 검증")
    print("=" * 60)
    all_failures += verify_file("guard.yml", _GUARD_YML, min_patterns=2)

    print()
    print("=" * 60)
    print("ci.yml 검증")
    print("=" * 60)
    all_failures += verify_file("ci.yml", _CI_YML, min_patterns=4)

    print()
    if all_failures:
        print(f"FAIL: {len(all_failures)}건의 검증 실패", file=sys.stderr)
        for f in all_failures:
            print(f"  - {f}", file=sys.stderr)
        sys.exit(1)
    else:
        print("PASS")
        sys.exit(0)
