"""build_performance_readiness_replay_bridge_v1.py — P1-009: Performance Readiness Replay Bridge

REPLAY 표본(REPLAY_BACKFILL/REPLAY_FROM_KRX_EOD)은 성과 지표 집계 혼입 금지(spec/29).
LIVE/PAPER 표본이 30건 이상 축적돼야 PERFORMANCE_READY 판정.
현재 인프라 구축 단계: gate=WATCH_PENDING_LIVE_SAMPLE.
"""
from __future__ import annotations

import argparse
import json
import statistics
from collections import Counter
from datetime import datetime, timezone
from pathlib import Path

from v7_hardening_common import ROOT, TEMP, load_json, save_json

DEFAULT_HIST = ROOT / "Temp" / "proposal_evaluation_history.json"
DEFAULT_OUT  = TEMP / "performance_readiness_replay_bridge_v1.json"

LIVE_SAMPLE_MIN = 30    # gate PERFORMANCE_READY 조건
LIVE_T20_PASS_RATE_MIN = 60.0

_REPLAY_ORIGINS = {"REPLAY_FROM_KRX_EOD", "REPLAY_BACKFILL"}
_REPLAY_VALIDATION = {"REPLAY_BACKFILL"}


def _is_replay(r: dict) -> bool:
    return (
        str(r.get("data_origin") or "").upper() in _REPLAY_ORIGINS
        or str(r.get("validation_status") or "").upper() in _REPLAY_VALIDATION
        or str(r.get("record_type") or "").upper().startswith("HISTORICAL_REPLAY")
    )


def _pass_rate(records: list[dict], outcome_key: str) -> float:
    matched = [r for r in records if r.get(outcome_key) == "MATCHED"]
    return round(len(matched) / len(records) * 100.0, 2) if records else 0.0


def _avg_return(records: list[dict], ret_key: str) -> float | None:
    vals = [r[ret_key] for r in records if r.get(ret_key) is not None]
    return round(statistics.mean(vals), 4) if vals else None


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--hist", default=str(DEFAULT_HIST))
    ap.add_argument("--out",  default=str(DEFAULT_OUT))
    args = ap.parse_args()

    hist_raw = load_json(Path(args.hist))
    records: list[dict] = hist_raw.get("records", []) if isinstance(hist_raw, dict) else (hist_raw if isinstance(hist_raw, list) else [])

    # ── 분류 ────────────────────────────────────────────────────────────────
    live_all  = [r for r in records if not _is_replay(r)]
    replay_all = [r for r in records if _is_replay(r)]

    live_t20  = [r for r in live_all  if r.get("t20_evaluation_status") == "EVALUATED_T20"]
    replay_t20 = [r for r in replay_all if r.get("t20_evaluation_status") == "EVALUATED_T20"]

    live_t5   = [r for r in live_all  if r.get("t5_evaluation_status") == "EVALUATED_T5"]
    replay_t5 = [r for r in replay_all if r.get("t5_evaluation_status") == "EVALUATED_T5"]

    live_t20_count  = len(live_t20)
    replay_t20_count = len(replay_t20)

    # ── LIVE 성과 지표만 집계 (spec/29: REPLAY 혼입 금지) ──────────────────
    live_t20_pass_rate = _pass_rate(live_t20, "t20_outcome")
    live_t20_avg_ret   = _avg_return(live_t20, "t20_return_pct")
    live_t5_pass_rate  = _pass_rate(live_t5, "t5_outcome")

    # ── REPLAY 정보용 통계 (성과 지표로 사용 금지) ─────────────────────────
    replay_t20_pass_rate = _pass_rate(replay_t20, "t20_outcome")  # informational only
    replay_t20_avg_ret   = _avg_return(replay_t20, "t20_return_pct")  # informational only

    # ── gate 판정 ────────────────────────────────────────────────────────────
    if live_t20_count >= LIVE_SAMPLE_MIN and live_t20_pass_rate >= LIVE_T20_PASS_RATE_MIN:
        gate = "PERFORMANCE_READY"
        readiness_score = min(100.0, live_t20_pass_rate)
    elif live_t20_count >= LIVE_SAMPLE_MIN:
        gate = "WATCH_LIVE_BELOW_THRESHOLD"
        readiness_score = live_t20_pass_rate
    elif live_t20_count > 0:
        gate = "WATCH_PENDING_LIVE_SAMPLE"
        # 부분 반영: live 표본이 일부 있으면 비례 가산
        readiness_score = min(50.0, live_t20_count / LIVE_SAMPLE_MIN * 50.0)
    else:
        gate = "WATCH_PENDING_LIVE_SAMPLE"
        readiness_score = 0.0

    # ── replay vs live gap (live 표본 있을 때만 계산) ─────────────────────
    replay_vs_live_gap_pct: float | None = None
    if live_t20_count >= 5 and live_t20_avg_ret is not None and replay_t20_avg_ret is not None:
        replay_vs_live_gap_pct = round(abs(replay_t20_avg_ret - live_t20_avg_ret), 4)

    result = {
        "formula_id": "PERFORMANCE_READINESS_REPLAY_BRIDGE_V1",
        "generated_at": datetime.now(timezone.utc).isoformat(),
        "gate": gate,
        "readiness_gate": gate,
        "performance_readiness_score": round(readiness_score, 2),
        # ── live 집계 (성과 지표) ──────────────────────────────────────────
        "live": {
            "total_records": len(live_all),
            "t20_count": live_t20_count,
            "t5_count": len(live_t5),
            "t20_pass_rate_pct": live_t20_pass_rate,
            "t5_pass_rate_pct": live_t5_pass_rate,
            "t20_avg_return_pct": live_t20_avg_ret,
            "sample_gate": "PASS" if live_t20_count >= LIVE_SAMPLE_MIN else f"PENDING({live_t20_count}/{LIVE_SAMPLE_MIN})",
        },
        # ── replay 집계 (정보용 — 성과 지표로 사용 금지) ─────────────────
        "replay_informational": {
            "total_records": len(replay_all),
            "t20_count": replay_t20_count,
            "t5_count": len(replay_t5),
            "t20_pass_rate_pct": replay_t20_pass_rate,
            "t20_avg_return_pct": replay_t20_avg_ret,
            "note": "REPLAY 표본은 성과지표 산출 금지(spec/29). 인프라 상태 확인용만.",
        },
        # ── 종합 ──────────────────────────────────────────────────────────
        "replay_vs_live_gap_pct": replay_vs_live_gap_pct,
        "required_live_t20_count": LIVE_SAMPLE_MIN,
        "required_live_t20_pass_rate_pct": LIVE_T20_PASS_RATE_MIN,
        "targets": {
            "live_t20_count": f">={LIVE_SAMPLE_MIN}",
            "live_t20_pass_rate_pct": f">={LIVE_T20_PASS_RATE_MIN}",
            "replay_vs_live_gap_pct": "<=10 (live 집계 가능 시)",
        },
        "prohibitions": [
            "REPLAY 표본 성과지표 혼입 금지",
            "REPLAY T20를 operational_t20_count에 가산 금지",
            "live < 30 상태에서 PERFORMANCE_READY 판정 금지",
        ],
    }

    save_json(args.out, result)
    print(json.dumps(result, ensure_ascii=False, indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
