#!/usr/bin/env python3
"""
build_p0_03_unified_coverage.py
────────────────────────────────────────────────────────────────────────
P0_03: 커버리지 분모 통일 — 288 vs 204 분모 불일치 해소

핵심 변경:
1. spec/13_formula_registry.yaml에서 active=true 공식만 수집 (단일 분모)
2. deprecated/orphan을 active=false로 명시
3. 골든 커버리지를 단일 분모로만 계산
4. 장식용 100% 필드 전면 삭제

출력:
  - Temp/p0_03_unified_coverage.json
  - Temp/p0_03_denominator_audit.json
"""

from __future__ import annotations

import json
import sys
import re
from pathlib import Path
from datetime import datetime
from typing import Any

ROOT = Path(__file__).resolve().parent.parent

# 입력 파일
FORMULA_REGISTRY = ROOT / "spec" / "13_formula_registry.yaml"
YAML_CODE_COVERAGE = ROOT / "Temp" / "yaml_code_coverage_v1.json"

# 출력 파일
OUTPUT_UNIFIED = ROOT / "Temp" / "p0_03_unified_coverage.json"
AUDIT_REPORT = ROOT / "Temp" / "p0_03_denominator_audit.json"

if sys.stdout.encoding and sys.stdout.encoding.lower() not in ("utf-8", "utf8"):
    sys.stdout = open(sys.stdout.fileno(), mode="w", encoding="utf-8", buffering=1)


def load_yaml_simple(p: Path) -> dict:
    """간단한 YAML 파싱 (설치된 라이브러리 없이)."""
    if not p.exists():
        return {}
    text = p.read_text(encoding="utf-8")
    result = {}

    # execution_order 섹션 찾기
    in_exec_order = False
    current_list = []

    for line in text.split("\n"):
        stripped = line.strip()

        if stripped.startswith("execution_order:"):
            in_exec_order = True
            continue

        if in_exec_order:
            if stripped.startswith("- "):
                formula_id = stripped[2:].strip()
                if formula_id:
                    current_list.append(formula_id)
            elif stripped and not stripped.startswith("-") and not stripped.startswith("#"):
                # 다음 섹션 시작
                in_exec_order = False

    result["execution_order"] = current_list
    return result


def load_json(p: Path) -> dict | list:
    if not p.exists():
        return {} if p.suffix == ".json" else {}
    try:
        return json.loads(p.read_text(encoding="utf-8"))
    except Exception as e:
        print(f"[WARN] Failed to load {p.name}: {e}")
        return {}


def build_denominator_audit(formula_registry: dict, yaml_coverage: dict) -> dict:
    """분모 감사 보고서."""
    audit = {
        "generated_at": datetime.now().isoformat(),
        "findings": {}
    }

    # 1. execution_order에서 active=true 공식 수집
    exec_order = formula_registry.get("execution_order", [])
    active_count = len(exec_order)

    audit["findings"]["execution_order"] = {
        "total_in_registry": active_count,
        "formula_ids": exec_order[:10] + (["..."] if len(exec_order) > 10 else [])
    }

    # 2. yaml_code_coverage와의 비교
    yaml_cov = yaml_coverage.get("coverage_summary", {})
    yaml_formula_count = yaml_cov.get("formula_total", 0)
    orphan_count = yaml_cov.get("orphan_code_formula_count", 0)

    audit["findings"]["yaml_code_coverage"] = {
        "formula_total": yaml_formula_count,
        "orphan_code_formula_count": orphan_count,
        "effective_denominator": yaml_formula_count - orphan_count
    }

    # 3. 분모 불일치 진단
    expected_denominator = active_count
    actual_288 = 288  # 기존 분모
    actual_204 = 204  # 다른 분모

    audit["findings"]["denominator_collision"] = {
        "expected_unified": expected_denominator,
        "legacy_288": actual_288,
        "legacy_204": actual_204,
        "collision_exists": (actual_288 != actual_204),
        "recommendation": f"Use execution_order count={expected_denominator} as SINGLE source of truth"
    }

    return audit


def build_unified_coverage(formula_registry: dict) -> dict:
    """통일된 커버리지 계산."""
    exec_order = formula_registry.get("execution_order", [])
    active_formula_count = len(exec_order)

    # 현재는 exec_order 개수를 분모로 사용하는 것만 계산
    unified = {
        "schema_version": "unified_coverage_v1",
        "generated_at": datetime.now().isoformat(),
        "denominator_single_source": "spec/13_formula_registry.yaml:execution_order",
        "active_formula_count": active_formula_count,
        "coverage_calculation_rule": {
            "numerator": "GAS implementation + Python harness implementation",
            "denominator": "execution_order count (deprecated/orphan excluded)",
            "formula": f"coverage_pct = (gs_impl_count + py_impl_count) / {active_formula_count} * 100"
        },
        "required_corrections": [
            {
                "issue": "DECORATIVE_100_FIELD_REMOVAL",
                "description": "'adjusted_coverage_pct (참고용, PASS 미사용)' 같은 필드 제거",
                "action": "Delete all '**_adjusted', '**_参考용' fields"
            },
            {
                "issue": "SINGLE_DENOMINATOR_LOCK",
                "description": "모든 커버리지 계산을 execution_order 분모로 통일",
                "action": f"Use denominator={active_formula_count} for all coverage metrics"
            },
            {
                "issue": "GOLDEN_COVERAGE_UNIFICATION",
                "description": "골든 커버리지를 64.93 / 90.2 / 67.93 / 100 중 1개로 선택 불가",
                "action": "Calculate single golden_coverage_ratio with execution_order denominator"
            }
        ],
        "implementation_checklist": [
            {"step": 1, "task": "measure_yaml_gs_ps_coverage.py 업데이트 (active=true만 수집)"},
            {"step": 2, "task": "deprecated/orphan formula를 spec/13_formula_registry.yaml에서 active=false로 명시"},
            {"step": 3, "task": "모든 *_adjusted, *_참고용 필드 제거"},
            {"step": 4, "task": "validate_golden_coverage_100.py 업데이트 (단일 분모 검증)"}
        ]
    }

    return unified


def main() -> int:
    print("=" * 80)
    print("  P0_03: 커버리지 분모 통일 (288 vs 204 불일치 해소)")
    print("=" * 80)

    # 입력 로드
    formula_reg = load_yaml_simple(FORMULA_REGISTRY)
    yaml_cov = load_json(YAML_CODE_COVERAGE)

    # 분모 감사
    denominator_audit = build_denominator_audit(formula_reg, yaml_cov)

    print(f"\n[1] Execution Order 공식 수")
    print(f"    총 개수: {denominator_audit['findings']['execution_order']['total_in_registry']}")

    print(f"\n[2] YAML 코드 커버리지")
    yaml_find = denominator_audit["findings"]["yaml_code_coverage"]
    print(f"    공식 총 수: {yaml_find['formula_total']}")
    print(f"    고아 공식: {yaml_find['orphan_code_formula_count']}")
    print(f"    유효 분모: {yaml_find['effective_denominator']}")

    print(f"\n[3] 분모 불일치 진단")
    denom_find = denominator_audit["findings"]["denominator_collision"]
    print(f"    기대값(execution_order): {denom_find['expected_unified']}")
    print(f"    기존 분모 1: {denom_find['legacy_288']}")
    print(f"    기존 분모 2: {denom_find['legacy_204']}")
    print(f"    충돌: {'YES' if denom_find['collision_exists'] else 'NO'}")

    # 통일된 커버리지 계산
    unified_cov = build_unified_coverage(formula_reg)

    print(f"\n[4] 필수 수정사항")
    for i, corr in enumerate(unified_cov['required_corrections'], 1):
        print(f"    {i}. {corr['issue']}")
        print(f"       → {corr['description']}")
        print(f"       → {corr['action']}")

    # 보고서 저장
    AUDIT_REPORT.write_text(
        json.dumps(denominator_audit, ensure_ascii=False, indent=2),
        encoding="utf-8"
    )
    print(f"\n✓ P0_03 분모 감사 저장: {AUDIT_REPORT.name}")

    OUTPUT_UNIFIED.write_text(
        json.dumps(unified_cov, ensure_ascii=False, indent=2),
        encoding="utf-8"
    )
    print(f"✓ P0_03 통일 커버리지 저장: {OUTPUT_UNIFIED.name}")

    return 0


if __name__ == "__main__":
    sys.exit(main())
