# -*- coding: utf-8 -*-
"""
决策系统 (bionic) 两个 PMS 接口的实机探活 —— 只读, 不落任何表, 不产生任何指令
==============================================================================
运行 (factorevaluation, 需 .env 能连参数表; --base 显式给地址则连参数表也不用):

  docker compose run --rm --no-deps pms-web python scripts/probe_bionic.py
  docker compose run --rm --no-deps pms-web python scripts/probe_bionic.py \
      --base http://192.168.16.178:38000 --code 600000.SH

探两件事 (待办 #9 / #10 的接通自证, 契约见 BIONIC_PMS_INTERFACE.md):
  1. /api/intraday/pms_exec   择时研判: 送一份手造的现场快照, 看回不回 FIRE/WAIT/UNAVAILABLE
  2. /api/intraday/pms_judge  研判闸:   送一份手造的 DCA 候选, 看回不回 PASS/REJECT
     (研判走 LLM, 30~90 秒是正常的; --skip-judge 可只探择时)

判读:
  * exec 回 UNAVAILABLE 时看原因——「无实时价」(收盘后正常)、「没有昨夜结论/已过期」
    (该股不在决策系统每晚分析范围, 换一只探) 都是正常降级不是故障; 盘中探到 FIRE/WAIT 才算全通。
  * judge 回 UNAVAILABLE —— 看 reason: 队列超时说明 brain_queue 拥堵 (考虑独立队列),
    连接拒绝说明地址/网络不通。
  * 两个都通了: 页面把 PMS_JUDGE_API_BASE 填上 (研判闸即生效),
    要切择时A再把 PMS_EXEC_IMPL 改成 A。
"""
import argparse
import json
import os
import sys
import time

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--base", default="", help="bionic 根地址; 缺省读参数 "
                    "PMS_EXEC_API_BASE / PMS_JUDGE_API_BASE")
    ap.add_argument("--code", default="600000.SH", help="探活用股票代码 (点式)")
    ap.add_argument("--skip-judge", action="store_true", help="只探择时, 不打 LLM")
    ap.add_argument("--judge-timeout", type=int, default=120)
    args = ap.parse_args()

    import requests

    base = args.base.rstrip("/")
    if not base:
        from app.services import exec_advisor, judge
        base = exec_advisor.base_url() or judge.base_url()
        if not base:
            print("[FAIL] 没有可用地址: --base 未给, PMS_EXEC_API_BASE / "
                  "PMS_JUDGE_API_BASE 也都为空")
            sys.exit(2)
    print(f"目标: {base}  探活代码: {args.code}")

    # ---- 1. 择时研判 (纯代码, 应当秒回) ----
    exec_payload = {
        "direction": "PMS_EXEC", "ts_code": args.code, "side": "buy", "action": "OPEN",
        "qty_left": 500, "is_last_day": False, "tdays_left": 3,
        "now": time.strftime("%H:%M"),
        "day": {"price": None, "vwap": None, "open": None, "high": None, "low": None,
                "day_chg_from_open": None, "bars": 0},   # 现场快照留空 → 由 bionic 自取实时价
        "refs": {"support": None, "pressure": None, "stop": None, "source": None},
        "position": {"total_qty": 0, "avail_qty": 0, "avg_cost": None, "cushion_pct": None},
    }
    t0 = time.time()
    try:
        r = requests.post(f"{base}/api/intraday/pms_exec", json=exec_payload, timeout=15)
        body = r.json()
        ms = (time.time() - t0) * 1000
        verdict = str(body.get("verdict") or "?")
        ok = verdict in ("FIRE", "WAIT", "UNAVAILABLE")
        print(f"[{'OK' if ok else 'FAIL'}] pms_exec {r.status_code} {ms:.0f}ms → {verdict}: "
              f"{body.get('reason')}")
        print("      " + json.dumps({k: body.get(k) for k in
                                     ("limit_price", "valid_min", "confidence", "missing",
                                      "advisor")}, ensure_ascii=False))
        exec_ok = ok
    except Exception as e:
        print(f"[FAIL] pms_exec 打不通: {type(e).__name__}: {e}")
        exec_ok = False

    # ---- 2. 研判闸 (LLM, 慢是正常) ----
    judge_ok = None
    if not args.skip_judge:
        judge_payload = {
            "direction": "PMS_JUDGE", "action": "DCA", "ts_code": args.code, "qty": 200,
            "reason": "[探活] 浮亏 -8.5% 触发第一档补仓评估",
            "hard_numbers": {"cushion_pct": -0.085, "stage": 1, "price": None},
            "context": {"position": {"ts_code": args.code, "avg_cost": None,
                                     "total_qty": 1000, "cushion_pct": -0.085},
                        "recent_ledger": [], "probe": True},
            "must_answer": ["下跌是杀逻辑还是杀情绪"],
        }
        print(f"研判闸探活中 (走 LLM, 最多等 {args.judge_timeout}s)...")
        t0 = time.time()
        try:
            r = requests.post(f"{base}/api/intraday/pms_judge", json=judge_payload,
                              timeout=args.judge_timeout)
            body = r.json()
            sec = time.time() - t0
            verdict = str(body.get("verdict") or "?")
            judge_ok = verdict in ("PASS", "REJECT")
            tag = "OK" if judge_ok else ("WARN" if verdict == "UNAVAILABLE" else "FAIL")
            print(f"[{tag}] pms_judge {r.status_code} {sec:.1f}s → {verdict} "
                  f"(confidence={body.get('confidence')}): {body.get('reason')}")
        except Exception as e:
            print(f"[FAIL] pms_judge 打不通: {type(e).__name__}: {e}")
            judge_ok = False

    print("-" * 60)
    if exec_ok and judge_ok:
        print("两个接口都通。下一步: 页面填 PMS_JUDGE_API_BASE=" + base
              + " (研判闸即生效); 要切择时A再把 PMS_EXEC_IMPL 改成 A")
    elif exec_ok and judge_ok is None:
        print("择时接口通 (--skip-judge 未探研判闸)")
    sys.exit(0 if exec_ok and judge_ok is not False else 1)


if __name__ == "__main__":
    main()
