"""
test_weight_change.py — 重み変更による順位変動テスト
W_SYMBOL を 0.20 → 0.50 に上げたとき、のだや・笹乃雪など象徴店のスコアが上がることを確認。
"""
import sys, json, os

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from nba_engine import (
    load_params, calc_p_convert, calc_v_expected,
    calc_s_strategic_with_factors, calc_c_action, determine_nba, ACTION_NAMES,
    DEFAULT_PARAMS,
)

DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "data")
PARAMS_PATH = os.path.join(DATA_DIR, "nba_params.json")
MASTER_PATH = os.path.join(DATA_DIR, "meiten-master.json")

with open(MASTER_PATH, encoding="utf-8") as f:
    master = json.load(f)
stores = master["stores"]

# ---- 通常パラメータ ----
p_base = load_params(PARAMS_PATH)
# ---- W_SYMBOL を 0.20 → 0.50 に上げたパラメータ（他は変えない）----
# ※ 重み合計 = 0.30+0.20+0.15+0.50+0.15 = 1.30 (1.0超だが仕様上 OK・警告が出るだけ)
p_sym = dict(p_base)
p_sym["W_SYMBOL"] = 0.50


def score_store(store, p):
    s, factors = calc_s_strategic_with_factors(store, p)
    nba = determine_nba(store, p)
    ev = (calc_p_convert(store) * calc_v_expected(store) * s) - calc_c_action(nba["action_type"], p)
    return {"s_strategic": s, "ev": ev, "factors": factors, "priority": nba["priority"]}


# ---- のだや (MTN-050) と 笹乃雪 の個別確認 ----
target_names = ["のだや", "笹乃雪"]
print("=" * 60)
print("■ 対象店 個別スコア変化")
print("=" * 60)
found_count = 0
for s in stores:
    if any(n in s.get("name", "") for n in target_names):
        found_count += 1
        base = score_store(s, p_base)
        high_sym = score_store(s, p_sym)
        print(f"\n[{s['storeId']}] {s['name']}")
        print(f"  sub_factors  : {base['factors']}")
        print(f"  s_strategic  (W_SYM=0.20): {base['s_strategic']:.3f}  |  ev={int(base['ev']):,}")
        print(f"  s_strategic  (W_SYM=0.50): {high_sym['s_strategic']:.3f}  |  ev={int(high_sym['ev']):,}")
        diff_s = high_sym["s_strategic"] - base["s_strategic"]
        diff_e = int(high_sym["ev"]) - int(base["ev"])
        print(f"  変化: Δs={diff_s:+.3f}  Δev={diff_e:+,}")
        assert diff_s >= 0, f"ERROR: {s['name']} の s_strategic が下がった（symbol スコア={base['factors']['symbol']:.3f}）"

if found_count == 0:
    print("  ※ のだや・笹乃雪 は見つかりませんでした（storeId要確認）")

# ---- 全店で Top10 比較 ----

def build_ranked(stores, p):
    results = []
    for s in stores:
        nba = determine_nba(s, p)
        s_val, _ = calc_s_strategic_with_factors(s, p)
        ev = (calc_p_convert(s) * calc_v_expected(s) * s_val) - calc_c_action(nba["action_type"], p)
        results.append((s, nba, ev))
    ev_min = min(r[2] for r in results)
    ev_max = max(r[2] for r in results)
    ev_rng = ev_max - ev_min
    ranked = []
    for s, nba, ev in results:
        if nba["action_type"] == "A10":
            ps = 0
        elif ev_rng == 0:
            ps = 50
        else:
            ps = max(0, min(100, int((ev - ev_min) / ev_rng * 100)))
        ranked.append({
            "storeId": s["storeId"],
            "name": s["name"],
            "priority": nba["priority"],
            "ps": ps,
            "ev": int(ev),
        })
    pri_ord = {"P0": 0, "P1": 1, "P2": 2, "P3": 3}
    ranked.sort(key=lambda x: (pri_ord.get(x["priority"], 9), -x["ps"]))
    return ranked


base_ranked = build_ranked(stores, p_base)
sym_ranked  = build_ranked(stores, p_sym)

print("\n" + "=" * 60)
print(f"■ Top10 変化  (W_SYMBOL 0.20→0.50, 他の重みはそのまま)")
print("=" * 60)
print(f"{'#':>2}  {'Base':<32}  →  {'W_SYMBOL高':<32}")
for i in range(10):
    b = base_ranked[i]
    s2 = sym_ranked[i]
    bstr = f"{b['priority']} {b['name'][:18]} ps={b['ps']}"
    sstr = f"{s2['priority']} {s2['name'][:18]} ps={s2['ps']}"
    changed = "" if b["storeId"] == s2["storeId"] else "  ← 変動"
    print(f"{i+1:>2}  {bstr:<35}  {sstr}{changed}")

# ---- 確認: 202件すべてにサブ因子があるか ----
print("\n" + "=" * 60)
print("■ サブ因子出力 202店確認")
print("=" * 60)
factors_path = os.path.join(DATA_DIR, "nba_factors.json")
with open(factors_path, encoding="utf-8") as f:
    fdata = json.load(f)
n_stores = len(fdata.get("stores", []))
n_with_factors = sum(1 for s in fdata["stores"] if s.get("sub_factors"))
print(f"  総店数: {n_stores}  サブ因子あり: {n_with_factors}")
assert n_stores == 202, f"ERROR: 店数が202でない ({n_stores})"
assert n_with_factors == 202, f"ERROR: サブ因子欠けあり ({n_with_factors}/202)"

# ---- 確認: model_version が 1.1.0 ----
output_path = os.path.join(DATA_DIR, "nba_output.json")
with open(output_path, encoding="utf-8") as f:
    odata = json.load(f)
mv = (odata.get("_meta") or {}).get("model_version")
print(f"  model_version: {mv}")
assert mv == "1.1.0", f"ERROR: model_version が {mv}"

print("\n[ALL TESTS PASSED]")
