from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Any


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_HISTORY = ROOT / "Temp" / "proposal_evaluation_history.json"
DEFAULT_OUTCOME = ROOT / "Temp" / "outcome_quality_score_v1.json"
DEFAULT_EXEC = ROOT / "Temp" / "execution_quality_harness_v1.json"
DEFAULT_PERF = ROOT / "Temp" / "perf_recovery_harness_v1.json"
DEFAULT_OUT = ROOT / "Temp" / "operational_outcome_lock_v1.json"


def _load(path: Path) -> dict[str, Any]:
    if not path.exists():
        return {}
    try:
        obj = json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return {}
    return obj if isinstance(obj, dict) else {}


def _f(v: Any, default: float = 0.0) -> float:
    try:
        return float(v)
    except Exception:
        return default


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--history", default=str(DEFAULT_HISTORY))
    ap.add_argument("--outcome", default=str(DEFAULT_OUTCOME))
    ap.add_argument("--execution", default=str(DEFAULT_EXEC))
    ap.add_argument("--perf", default=str(DEFAULT_PERF))
    ap.add_argument("--out", default=str(DEFAULT_OUT))
    args = ap.parse_args()

    hp = Path(args.history)
    op = Path(args.outcome)
    ep = Path(args.execution)
    pp = Path(args.perf)
    out = Path(args.out)
    if not hp.is_absolute():
        hp = ROOT / hp
    if not op.is_absolute():
        op = ROOT / op
    if not ep.is_absolute():
        ep = ROOT / ep
    if not pp.is_absolute():
        pp = ROOT / pp
    if not out.is_absolute():
        out = ROOT / out

    history = _load(hp)
    outcome = _load(op)
    execution = _load(ep)
    perf = _load(pp)

    records = history.get("records") if isinstance(history.get("records"), list) else []
    t5_oper = [
        r for r in records if isinstance(r, dict)
        and r.get("t5_evaluation_status") == "EVALUATED_T5"
        and str(r.get("validation_status") or "").upper() != "REPLAY_BACKFILL"
    ]
    t20_oper = [
        r for r in records if isinstance(r, dict)
        and r.get("t20_evaluation_status") == "EVALUATED_T20"
        and str(r.get("validation_status") or "").upper() != "REPLAY_BACKFILL"
    ]
    t20_match = len([r for r in t20_oper if str(r.get("t20_outcome") or "") == "MATCHED"])
    t20_rate = round((t20_match / len(t20_oper)) * 100.0, 2) if t20_oper else 0.0

    oq_score = _f(outcome.get("score"))
    eq_metrics = (execution.get("metrics") or {}).get("operational_t20") if isinstance((execution.get("metrics") or {}).get("operational_t20"), dict) else {}
    expectancy = _f(eq_metrics.get("expectancy_pct"))
    win_rate = _f(eq_metrics.get("win_rate_pct"))
    late_precision = _f((perf.get("metrics") or {}).get("late_chase_block_precision"), 0.0)
    value_damage = _f((perf.get("metrics") or {}).get("rebound_sell_value_damage"), 0.0)

    # [Work 29] threshold 현실화
    # execution_quality_harness_v1.json 미존재 시 EXPECTANCY/WIN_RATE는 "데이터 없음"으로 처리
    # (실거래 기록 없음 = 알 수 없음, 아닌 0%)
    _exec_data_available = ep.exists() and bool(eq_metrics)

    reasons: list[str] = []
    if len(t20_oper) < 30:
        reasons.append("OPERATIONAL_T20_SAMPLE_LT_30")
    if t20_rate < 60.0:
        reasons.append("OPERATIONAL_T20_PASS_LT_60")
    if oq_score < 60.0:
        reasons.append("OUTCOME_QUALITY_LT_60")
    # EXPECTANCY/WIN_RATE: 실거래 T+20 표본이 충분할 때만 체크 (samples>0)
    _exec_samples = int(_f(eq_metrics.get("samples"), 0.0))
    if _exec_data_available and _exec_samples >= 10:
        if expectancy <= 0.1:
            reasons.append("EXPECTANCY_LE_0_1")
        if win_rate < 45.0:
            reasons.append("WIN_RATE_LT_45")
    # VALUE_DAMAGE: 10% 초과는 실행 차단
    if value_damage > 10.0:
        reasons.append("VALUE_DAMAGE_GT_10")
    if late_precision < 80.0 and late_precision > 0.0:
        reasons.append("LATE_CHASE_PRECISION_LOW")

    unlock_state = "PERFORMANCE_READY" if not reasons else "WATCH_PENDING_SAMPLE"
    if any(x in reasons for x in ("OUTCOME_QUALITY_LT_60", "EXPECTANCY_LE_0_1", "WIN_RATE_LT_45", "VALUE_DAMAGE_GT_10")):
        unlock_state = "NOT_PERFORMANCE_READY"

    result = {
        "formula_id": "OPERATIONAL_OUTCOME_LOCK_V1",
        "unlock_state": unlock_state,
        "reasons": reasons,
        "metrics": {
            "operational_t5_count": len(t5_oper),
            "operational_t20_count": len(t20_oper),
            "operational_t20_pass_rate": t20_rate,
            "outcome_quality_score": oq_score,
            "execution_expectancy_pct": expectancy,
            "execution_win_rate_pct": win_rate,
            "late_chase_block_precision": late_precision,
            "sell_after_rebound_damage_pct": value_damage,
        },
        "targets": {
            "operational_t20_count_min": 30,
            "operational_t20_pass_rate_min": 60.0,
            "outcome_quality_score_min": 60.0,
            "execution_expectancy_pct_min": 0.1,
            "execution_win_rate_pct_min": 45.0,
            "sell_after_rebound_damage_pct_max": 10.0,
        },
    }

    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
    print(json.dumps(result, ensure_ascii=False, indent=2))
    return 0


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