from __future__ import annotations

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


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_JSON = ROOT / "GatherTradingData.json"
DEFAULT_OUT = ROOT / "Temp" / "cash_raise_value_optimizer_v3.json"


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


def _rows(v: Any) -> list[dict[str, Any]]:
    if isinstance(v, list):
        return [x for x in v if isinstance(x, dict)]
    if isinstance(v, str):
        try:
            return _rows(json.loads(v))
        except Exception:
            return []
    return []


def _obj(v: Any) -> dict[str, Any]:
    if isinstance(v, dict):
        return v
    if isinstance(v, str):
        try:
            x = json.loads(v)
            return x if isinstance(x, dict) else {}
        except Exception:
            return {}
    return {}


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


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

    jp = Path(args.json)
    op = Path(args.out)
    if not jp.is_absolute():
        jp = ROOT / jp
    if not op.is_absolute():
        op = ROOT / op

    payload = _load(jp)
    data = payload.get("data") if isinstance(payload.get("data"), dict) else {}
    h = data.get("_harness_context") if isinstance(data.get("_harness_context"), dict) else {}
    if isinstance(payload.get("hApex"), dict):
        h = dict(h) | payload["hApex"]

    cash_shortfall = _f(h.get("cash_shortfall_min_krw"))
    scrs = _obj(h.get("scrs_v2_json"))
    selected = _rows(scrs.get("selected_combo"))
    if not selected:
        selected = _rows(h.get("trim_plan_to_min_cash_json"))

    ranked = sorted(selected, key=lambda r: (_f(r.get("value_damage_pct")), -_f(r.get("expected_sell_krw"))))
    immediate_total = _f(scrs.get("total_immediate_sell_krw"))
    rebound_gain = _f(scrs.get("expected_rebound_gain_krw"))
    value_damage = _f(scrs.get("value_damage_pct_avg"))
    cash_after = max(0.0, cash_shortfall - immediate_total)
    objective = round(
        cash_after * 1.0
        + value_damage * 10000.0
        - rebound_gain * 0.1,
        2,
    )

    orders = []
    for r in ranked[:10]:
        orders.append(
            {
                "ticker": r.get("ticker"),
                "name": r.get("name"),
                "immediate_qty": r.get("immediate_qty", r.get("sell_qty")),
                "rebound_wait_qty": r.get("rebound_wait_qty", 0),
                "estimated_immediate_krw": r.get("expected_sell_krw", r.get("estimated_sell_krw", 0)),
                "value_damage_pct": r.get("value_damage_pct"),
            }
        )

    out = {
        "formula_id": "CASH_RAISE_VALUE_OPTIMIZER_V3",
        "objective_score": objective,
        "cash_target_krw": round(cash_shortfall),
        "cash_raised_immediate_krw": round(immediate_total),
        "cash_raised_rebound_krw": round(max(0.0, _f(scrs.get("total_projected_sell_krw")) - immediate_total)),
        "expected_rebound_gain_krw": round(rebound_gain),
        "value_damage_pct_avg": round(value_damage, 2),
        "leader_damage_score": round(value_damage * 1.2, 2),
        "cluster_risk_after_pct": round(_f(_obj(h.get("mandatory_reduction_json")).get("cluster_pct")), 2),
        "orders": orders,
    }

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


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

