"""図面のある大型店（⑧⑨）の試算の結果と平面図を、公開中の試算のページに足す（2026-11-02）
使い方: python3 build_page_large.py <公開中のページ> <大型店の results.json> <出力するページ> [--replace large_p7 ...]
  --replace：もう入っている店を入れ替える（その店の行・店・平面図を消してから足し直す。2026-11-02 に⑨の店の形を直したとき）

- 前からある条件の行・店・平面図は変えない。大型店の図面のある店（large_p6・large_p7）の店・平面図・行を後ろに足す
- 画面：店の形を選ぶ欄を、標準ファミレスに加えて大型店でも出す（もとにする店ごとに、その店の図面だけを並べる）
- 結果の前提（common・回数）が今の haizen_sim.py と同じことを確かめる"""
import json
import os
import sys

import haizen_sim as h

live, res, out = sys.argv[1:4]
REPLACE = sys.argv[sys.argv.index("--replace") + 1:] if "--replace" in sys.argv else []
KEYS = REPLACE or ["large_p6", "large_p7"]
SHORT = {"large_p6": "⑧ 大型・受け渡し口が奥の真ん中", "large_p7": "⑨ 大型・厨房が右・入口が角"}

s = open(live, encoding="utf-8").read()
N = json.load(open(res, encoding="utf-8"))
assert N["common"] == json.loads(json.dumps(h.COMMON)), "結果が今の haizen_sim.py の前提と違う"
assert N["reps"] == h.REPS

lines = s.split("\n")
idx = [i for i, l in enumerate(lines) if l.startswith("const D = ")]
assert len(idx) == 1
D = json.loads(lines[idx[0]][len("const D = "):].rstrip(";"))
K = D["k"]
cond, mets = K[:8], K[8:-1]
assert cond == ["store", "staff", "robots", "arrivals_per_h", "mode", "trays", "fragile_by", "registers"] and K[-1] == "ng"
if REPLACE:
    assert all(k in D["stores"] for k in KEYS), "入れ替える店がまだ入っていない"
    D["r"] = [r for r in D["r"] if r[0] not in KEYS]
    for k in KEYS:
        D["stores"].pop(k)
        D["plans"].pop(k)
else:
    assert not any(k in D["stores"] for k in KEYS), "もう入っている"
assert {k: v for k, v in D["common"].items()} == json.loads(json.dumps(h.COMMON)), "ページの前提と今の試算の前提が違う"

# 行：条件の並び（haizen_sim.conditions()）のうち大型店の図面のある店の分を、全部そろっているか確かめて足す
rows = {h.key(r): r for r in N["rows"]}
conds = [c for c in h.conditions() if c["store"] in KEYS]
missing = [c for c in conds if h.key(c) not in rows]
assert not missing, f"結果が足りない：{len(missing)} 条件"
for c in conds:
    r = rows[h.key(c)]
    D["r"].append([c[k] for k in cond] + [round(r[k], 3) for k in mets] + [1 if r["staff_wait_mean"] >= h.NG_MIN else 0])

# 店と平面図：public/sim/layouts/large/ の店の形から
gens = set()
for k in KEYS:
    st = {a: b for a, b in h.STORES[k].items() if a != "dist_list"}
    nm = st["layout"]
    f = [x for x in os.listdir(h.LAYOUT_DIR_LARGE) if x.startswith(nm + "_") and x.endswith("_analysis.json")][0]
    A = json.load(open(os.path.join(h.LAYOUT_DIR_LARGE, f), encoding="utf-8"))
    Lf = json.load(open(os.path.join(h.LAYOUT_DIR_LARGE, f.replace("_analysis.json", ".json")), encoding="utf-8"))
    gens |= {A["meta"]["generation"], Lf["meta"]["generation"]}
    L = Lf["layout"]
    st.update(label=f"大型店（{SHORT[k]}）", short=SHORT[k], dist_m=list(st["dist_m"]), dist_mean=A["summary"]["robot_dist_mean"])
    D["stores"][k] = st
    W, Dp = L["outer"]["w"], L["outer"]["d"]
    D["plans"][k] = dict(
        w=W, d=Dp, outline=L.get("outline") or [[0, 0], [W, 0], [W, Dp], [0, Dp]],
        rooms=[[*r["rect"], r.get("kind", "back"), r["label"]] for r in L["rooms"]],
        walls=[w["rect"] for w in L["walls"]],
        tables=[[t["x"], t["y"], round(t["x"] + t["w"], 3), round(t["y"] + t["h"], 3), t["seats"]] for t in L["tables"]],
        dish=[d["rect"] for d in L["dish_up"]], standby=L["robot_standby"]["rect"],
        ent=[L["entrance"]["side"], L["entrance"]["a0"], L["entrance"]["a1"]])
assert len(gens) == 1, gens
D["layout_generation_large"] = gens.pop()
lines[idx[0]] = "const D = " + json.dumps(D, ensure_ascii=False, separators=(",", ":")) + ";"
s = "\n".join(lines)


def rep(a, b):
    global s
    assert s.count(a) == 1, (a, s.count(a))
    s = s.replace(a, b)


if REPLACE:   # 画面の書き替えは最初に足したときに済んでいる
    open(out, "w", encoding="utf-8").write(s)
    print(out, len(D["r"]), "rows", "large gen", D["layout_generation_large"], "replaced", KEYS)
    sys.exit(0)
# もとにする店（図面のある店なら base、そうでなければ自分）
rep("const isLayout = k => !!(STORES[k] && STORES[k].layout);",
    "const isLayout = k => !!(STORES[k] && STORES[k].layout);\n"
    "// 図面のある店のもとにする店（標準ファミレス・大型店。2026-11-02 に大型店を足した）\n"
    "const baseOf = k => (STORES[k] && STORES[k].base) || k;\n"
    "const LAYOUT_BASES = [...new Set(LAYOUT_KEYS.map(baseOf))];")
rep('''  const on = state.store === "family" || isLayout(state.store);
  el.hidden = !on;
  if (!on) return;
  const fam = STORES.family;
  const items = [["family", "① 図面なし", `${fam.tables}卓・${fam.dist_m[0]}〜${fam.dist_m[1]}m`, `<div class="noplan">距離の幅だけで試算</div>`]]
    .concat(LAYOUT_KEYS.map(k => { const s = STORES[k]; return [k, s.short, `${s.tables}卓・${s.dist_m[0]}〜${s.dist_m[1]}m`, PLANS[k] ? planSvg(PLANS[k]) : ""]; }));
  el.innerHTML = `<p class="lay-h">店の形を選ぶ（標準ファミレス）。平面図から、卓の数と厨房から卓までの距離を取ります</p>`''',
    '''  const base = baseOf(state.store);
  const on = LAYOUT_BASES.includes(base);
  el.hidden = !on;
  if (!on) return;
  const fam = STORES[base];
  const items = [[base, base === "family" ? "① 図面なし" : "図面なし", `${fam.tables}卓・${fam.dist_m[0]}〜${fam.dist_m[1]}m`, `<div class="noplan">距離の幅だけで試算</div>`]]
    .concat(LAYOUT_KEYS.filter(k => baseOf(k) === base).map(k => { const s = STORES[k]; return [k, s.short, `${s.tables}卓・${s.dist_m[0]}〜${s.dist_m[1]}m`, PLANS[k] ? planSvg(PLANS[k]) : ""]; }));
  el.innerHTML = `<p class="lay-h">店の形を選ぶ（${fam.label}）。平面図から、卓の数と厨房から卓までの距離を取ります</p>`''')
rep('const on = state.store === k || (k === "family" && isLayout(state.store));',
    'const on = state.store === k || (isLayout(state.store) && k === baseOf(state.store));')
rep('`標準ファミレス（${STORES.family.tables}卓）を、卓の数（${s.tables}卓）に合わせて増減。ほかの前提は標準ファミレスと同じ`',
    '`${STORES[s.base].label}（${STORES[s.base].tables}卓）を、卓の数（${s.tables}卓）に合わせて増減。ほかの前提は${STORES[s.base].label}と同じ`')
open(out, "w", encoding="utf-8").write(s)
print(out, len(D["r"]), "rows", "large gen", D["layout_generation_large"])
