#!/usr/bin/env python3
"""
validate_report_section_completeness_v1.py
모든 REPORT_SECTION_ORDER 섹션이 operational_report.json에 존재하고 비어있지 않은지 검증.
section_errors도 검사하여 처리 오류가 있으면 WARN 표기.
누락 섹션이 있으면 gate=FAIL 로 종료(exit 1).
"""
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]

REPORT_SECTION_ORDER = [
    "exec_safety_declaration", "final_judgment_table", "final_execution_decision",
    "concise_hts_input_sheet", "watch_breakout_gate",
    "reference_price_ledger",
    "single_conclusion", "immediate_execution_playbook", "market_context_learning_note",
    "portfolio_performance_summary",
    "portfolio_sector_exposure_summary",
    "sector_universe_refresh_audit_v1",
    "sector_trend_analysis_v1",
    "etf_representative_monitor_v1",
    "performance_readiness_summary",
    "operational_eval_queue_summary",
    "investment_quality_headline", "operational_truth_score",
    "execution_readiness_matrix", "pass_100_criteria",
    "today_decision_summary_card", "routing_serving_trace",
    "export_gate_diagnosis", "QEH_AUDIT_BLOCK",
    "backdata_feature_bank_table", "alpha_lead_table", "anti_distribution_table",
    "profit_preservation_table", "smart_cash_raise_table", "execution_quality_table",
    "decision_trace_table", "anti_whipsaw_reentry_gate", "proposal_reference_sheet",
    "satellite_buy_proposal_sheet", "core_satellite_timing_gate_table",
    "engine_feedback_loop_report", "prediction_evaluation_improvement_report",
    "rule_lifecycle_governance_report",
]

MISSING_DATA_TOKEN = "DATA_MISSING — 하네스 업데이트 필요"


def _missing_category(section_name: str) -> str:
    if section_name in {"fundamental_quality_gate_v1", "horizon_allocation_lock_v1", "smart_money_liquidity_gate_v1"}:
        return "core_signal_gap"
    if section_name in {"benchmark_relative_harness_table", "index_relative_health_table", "entry_freshness_gate_table", "sell_value_preservation_gate_table", "watch_release_checklist"}:
        return "market_gate_gap"
    if section_name in {"engine_feedback_loop_report", "prediction_evaluation_improvement_report", "performance_readiness_summary"}:
        return "performance_gate_gap"
    if section_name in {"alpha_lead_table", "anti_distribution_table", "profit_preservation_table", "smart_cash_raise_table", "execution_quality_table", "sell_priority_decision_table"}:
        return "decision_table_gap"
    return "other_gap"


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--report-json", default=str(ROOT / "Temp" / "operational_report.json"))
    args = ap.parse_args()

    path = Path(args.report_json)
    if not path.exists():
        print(f"[오류] 리포트 JSON 없음: {path}")
        return 1

    report = json.loads(path.read_text(encoding="utf-8"))
    sections_list = report.get("sections", [])
    section_errors = report.get("section_errors", [])

    present = {s["name"] for s in sections_list if s.get("name")}
    non_empty = {
        s["name"] for s in sections_list
        if s.get("name") and s.get("markdown", "").strip()
    }

    missing  = [n for n in REPORT_SECTION_ORDER if n not in present]
    empty    = [n for n in REPORT_SECTION_ORDER if n in present and n not in non_empty]
    err_names = [e["section"] for e in section_errors if isinstance(e, dict)]
    missing_data_rows = []
    for section in sections_list:
        if not isinstance(section, dict):
            continue
        name = str(section.get("name") or "")
        markdown = str(section.get("markdown") or "")
        if not name or name == "section_processing_errors":
            continue
        if MISSING_DATA_TOKEN not in markdown:
            continue
        missing_data_rows.append({
            "section": name,
            "category": _missing_category(name),
            "missing_line_count": sum(1 for line in markdown.splitlines() if MISSING_DATA_TOKEN in line),
        })

    # 결과 출력
    print(f"REPORT_SECTION_ORDER 기준: {len(REPORT_SECTION_ORDER)}개 섹션 검사")
    print(f"  - 존재:         {len([n for n in REPORT_SECTION_ORDER if n in present])}개")
    print(f"  - 누락(missing): {len(missing)}개")
    print(f"  - 빈 섹션(empty): {len(empty)}개")
    print(f"  - 처리 오류 섹션: {len(section_errors)}개")

    if missing:
        print("\n[FAIL] 누락 섹션 목록:")
        for n in missing:
            print(f"  MISSING: {n}")

    if empty:
        print("\n[WARN] 빈 섹션 목록:")
        for n in empty:
            print(f"  EMPTY: {n}")

    if section_errors:
        print(f"\n[WARN] 섹션 처리 오류 ({len(section_errors)}건):")
        for e in section_errors:
            if isinstance(e, dict):
                print(f"  ERROR: {e.get('section', '?')} — {e.get('error', '?')}")

    result = {
        "validator": "validate_report_section_completeness_v1",
        "total_expected": len(REPORT_SECTION_ORDER),
        "present": len([n for n in REPORT_SECTION_ORDER if n in present]),
        "missing": missing,
        "empty": empty,
        "section_error_count": len(section_errors),
        "section_errors": section_errors,
        "gate": "FAIL" if missing else "PASS",
    }

    out = ROOT / "Temp" / "report_section_completeness.json"
    out.write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding="utf-8")
    inventory_out = ROOT / "Temp" / "missing_data_inventory_v1.json"
    inventory_result = {
        "validator": "validate_report_section_completeness_v1",
        "section_count": len(sections_list),
        "missing_section_count": len(missing_data_rows),
        "categories": {},
        "sections": missing_data_rows,
    }
    for row in missing_data_rows:
        cat = row["category"]
        inventory_result["categories"][cat] = inventory_result["categories"].get(cat, 0) + 1
    inventory_out.write_text(json.dumps(inventory_result, indent=2, ensure_ascii=False), encoding="utf-8")
    print(f"\nREPORT_SECTION_COMPLETENESS: gate={result['gate']} missing={len(missing)} empty={len(empty)} section_errors={len(section_errors)}")
    print(f"OUTPUT: {out}")
    print(f"MISSING_DATA_INVENTORY: sections={len(missing_data_rows)} OUTPUT: {inventory_out}")

    if missing:
        return 1
    return 0


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