"""大型店の店の形（郊外のゆったり型・70卓まで）。2026-11-02 エイイチと決めた定義で作る試作

定義（2026-11-02）
- 大型店は郊外の店（都市部の大型店は採算が合いにくい）。ゆったり型：仕切り壁多め・ボックス席中心
- 卓は最大70卓くらい（⑤の46卓と差が出るように）
- 外寸 34m×22m（748㎡・約226坪）。厨房・洗い場は大きめ（2026-11-02 エイイチ）の横長。客席側の1卓あたりの広さは ⑤⑥（7.7〜8.1㎡）より広め
- 受け渡し口は「奥の真ん中」が基本。店の回し方で置き場所が変わるので、候補（パントリーの左寄り・右寄り）を選べるようにしておく（DISH_POS）。
  厨房・客席は3つとも同じで、変わるのは受け渡し口と待機場所だけ（比べたときの差が受け渡し口の位置だけになるように）
- レジ2つ・客用トイレ2か所・ドリンクバー2つ・ロボットの待機場所6台分
- 通路は今の店と同じ決まり（ロボットのふだんの道1.0m・最低0.8m）

作り方・確かめ・Unity の細かい形と地図は famires_v3 と同じ規則。公開している6店の形（public/sim/layouts/ の p0〜p5）は変えない。

使い方: python3 large_store.py [center|left|right|b] [--out DIR]   （b は ⑨ 厨房が右・入口が左下の角）
        python3 large_store.py --publish    （サイトに載せる⑧奥の真ん中・⑨を public/sim/layouts/large/ に出す）
"""
import json
import tempfile
import sys
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

import famires_v3 as F
from famires_gen2 import strip, island, two_seat_row, lsofa, register, toilet_block, UNIT
from famires_gen2 import boh_right as gen_boh_right

HERE = Path(__file__).resolve().parent
W, D = 34.0, 22.0   # 奥行きは厨房・洗い場を大きめにするため 20→22m（2026-11-02 エイイチ：大型店なのでキッチン・洗い場は大きめでよい）
BACK_W = 12.0      # 厨房側（パントリー・キッチン・洗い場・保存）の幅
FY = 11.8          # パントリーの客席側の辺（受け渡し口の y）

X0 = (W - BACK_W) / 2   # 厨房側は奥の真ん中に置いたまま。候補で動かすのは受け渡し口と待機場所だけ
# 受け渡し口の候補（パントリーの客席側の辺のどこに開けるか）。基本は真ん中。
# 待機場所（6台分）は受け渡し口の横で、厨房の真ん中の側に置く
DISH_POS = ("center", "left", "right")
NAMES = {"center": "受け渡し口が奥の真ん中", "left": "受け渡し口が奥の左寄り", "right": "受け渡し口が奥の右寄り"}


def back_block(x0, pos="center"):
    x1 = x0 + BACK_W
    mid = (x0 + x1) / 2
    rooms = [
        dict(label="パントリー", rect=[x0, FY, x1, FY + 1.2], kind="back"),
        dict(label="キッチン", rect=[x0, FY + 1.2, x1, D - 4.0], kind="back"),
        dict(label="洗い場", rect=[x0, D - 4.0, mid + 1.0, D], kind="back"),
        dict(label="冷蔵・冷凍・保存", rect=[mid + 1.0, D - 4.0, x1 - 3.0, D], kind="back"),
        dict(label="更衣室・社員トイレ", rect=[x1 - 3.0, D - 4.0, x1, D], kind="back"),
    ]
    c = {"center": mid, "left": x0 + 1.8, "right": x1 - 1.8}[pos]   # 受け渡し口の真ん中
    dish = [dict(label="受け渡し口", rect=[c - 1.5, FY, c + 1.5, FY + 0.4])]
    # 6台分（1台 0.8m）を横一列。真ん中と左寄りは受け渡し口の右、右寄りは左
    sx = c - 1.7 - 4.8 if pos == "right" else c + 1.7
    standby = dict(label="ロボット待機・充電", rect=[sx, FY - 0.85, sx + 4.8, FY - 0.05], slots=6)
    return rooms, dish, standby, [c, FY - 0.45]


def build(pos="center"):
    x0 = X0
    x1 = x0 + BACK_W
    rooms, dish, sb, start = back_block(x0, pos)
    walls = []
    # 客用トイレ2か所（左上・右上の角）
    tl, tw, td1 = toilet_block([0.0, D - 2.8, 3.0, D], "right", W, D)
    tr, tw2, td2 = toilet_block([W - 3.0, D - 2.8, W, D], "left", W, D)
    rooms += [tl, tr]
    walls += tw + tw2
    # 入口は正面（下の壁）の真ん中。左にレジ2つ（同じレジ内を挟まず、レジ内の右に縦に2つ）、右に待合
    ea0, ea1 = W / 2 - 1.5, W / 2 + 1.5
    rx = ea0 - 1.8   # レジのカウンターの左端
    rooms += [*register([rx, 0.3, rx + 0.7, 2.8], [rx - 0.8, 0.3, rx, 5.9]),
              dict(label="レジ", rect=[rx, 3.4, rx + 0.7, 5.9], kind="guest"),
              dict(label="待合", rect=[ea1 + 1.4, 0.3, ea1 + 1.9, 3.3], kind="guest"),
              # ドリンクバー2つ（厨房の左右の壁ぎわ。客席の左右それぞれから近い）
              dict(label="ドリンクバー", rect=[x0 - 0.7, 13.6, x0, 16.6], kind="drink"),
              dict(label="ドリンクバー", rect=[x1, 13.6, x1 + 0.7, 16.6], kind="drink")]

    t = []
    # ---- 左の客席
    t += strip(0.0, 1.4, "v", 7, walls=walls)                 # 左の壁ぞい（トイレの手前で止める）
    t += island(2.7, 3.4, "v", 5, walls=walls)
    t += island(6.75, 3.4, "v", 5, walls=walls)
    t += strip(4.4, D - 1.8, "h", 2, seats=6, walls=walls)    # 家族用の6人ボックス（上の壁ぞい・左）
    t += strip(1.6, 0.0, "h", 6, seats=6, walls=walls)        # 家族用の6人ボックス（下の壁ぞい・左）
    # ---- 右の客席（左と同じ並び）
    t += strip(W - 1.2, 1.4, "v", 7, walls=walls)
    t += island(W - 2.7 - 2.55, 3.4, "v", 5, walls=walls)
    t += island(W - 6.75 - 2.55, 3.4, "v", 5, walls=walls)
    t += strip(W - 4.4 - 2 * UNIT, D - 1.8, "h", 2, seats=6, walls=walls)
    t += strip(W - 1.6 - 6 * UNIT, 0.0, "h", 6, seats=6, walls=walls)
    L = dict(name=f"⑧ 大型店・郊外のゆったり型（{NAMES[pos]}）", style="ゆったり", outer=dict(w=W, d=D),
             entrance=dict(side="bottom", a0=ea0, a1=ea1), rooms=rooms, walls=walls, toilet_doors=[td1, td2],
             dish_up=dish, robot_standby=sb, start=start, tables=t)
    return L


def build_b():
    """⑨ 大型店のもう1つの形：厨房が右の壁ぞい（パントリーは縦長で、受け渡し口は下の端。③と同じ向き）・入口が左下の角。
    客席は右の厨房を除いた横長の1つの部屋に、ゆったりの島を5本並べる。卓の数・席の種類は⑧と同じ70卓"""
    # 厨房側：パントリーは縦長で奥の壁まで（洗い場への通り道を兼ねる）。キッチンの上に大きめの洗い場
    rooms = [dict(label="パントリー", rect=[24.3, 7.0, 26.3, D], kind="back"),
             dict(label="キッチン", rect=[26.3, 7.0, 31.0, 16.0], kind="back"),
             dict(label="冷蔵・冷凍・保存", rect=[31.0, 11.5, W, 16.0], kind="back"),
             dict(label="更衣室・社員トイレ", rect=[31.0, 7.0, W, 11.5], kind="back"),
             dict(label="洗い場", rect=[26.3, 16.0, W, D], kind="back")]
    walls = [dict(label="パントリーの壁", rect=[24.0, 7.0, 24.3, D])]
    dish = [dict(label="受け渡し口", rect=[24.3, 7.0, 26.3, 7.4])]
    # ロボットの待機場所は、パントリーの縦の壁ぞい（受け渡し口のすぐ上から6台分を縦に。2026-11-02 エイイチ）
    sb = dict(label="ロボット待機・充電", rect=[23.2, 7.4, 24.0, 12.2], slots=6)
    start = [25.3, 6.55]
    # 客用トイレは右下に大きめの1か所・男女別（2026-11-02 エイイチ：店の設計上、水回りはまとまっている方がよい。
    # 厨房・更衣室の社員トイレの下にまとめる）。下が男・上が女のつもり（Unity ではどちらも「トイレ」）。入口はどちらも左向き
    # 上の端は更衣室・社員トイレの下の辺（y 7.0）までのばし、厨房との間にすき間を残さない（2026-11-02 エイイチ）
    tm, tw, td1 = toilet_block([30.5, 0.0, W, 3.5], "left", W, D)
    tf, tw2, td2 = toilet_block([30.5, 3.5, W, 7.0], "left", W, D)
    rooms += [tm, tf]
    walls += tw + tw2
    rooms += [dict(label="待合", rect=[0.0, 0.9, 0.5, 3.6], kind="guest"),
              # 縦のカウンター2つ。客は入口の側（左）に立ち、入口へ向かって並ぶ（③と同じ置き方）
              # 2つ目は1つ目のすぐ上（レジの上の端と島の下の端の間を1.3m空け、左の客席へ下から入れるようにする）
              *register([3.6, 0.4, 4.3, 2.9], [4.3, 0.4, 5.1, 5.4]),
              dict(label="レジ", rect=[3.6, 2.9, 4.3, 5.4], kind="guest"),
              # ドリンクバーは1つにまとめて大きくし、上の壁ぎわのパントリーの近くに置く（2026-11-02 エイイチ）
              dict(label="ドリンクバー", rect=[17.6, D - 0.7, 24.0, D], kind="drink")]
    t = strip(0.0, 7.2, "v", 4, walls=walls)                  # 左の壁ぞい（レジの上から）
    for x in (2.7, 6.75, 10.8, 14.85, 18.9):                  # ゆったりの島を5本（間の通路1.5m）
        t += island(x, 6.9, "v", 5, walls=walls)
    t += strip(5.6, 0.0, "h", 8, seats=6, walls=walls)        # 家族用の6人ボックス（下の壁ぞい）
    # 右下にあった6人ボックス3つは、トイレにした所から上の壁ぞいへ移した（2026-11-02 エイイチ）
    t += strip(0.0, D - 1.8, "h", 8, seats=6, walls=walls)    # 家族用の6人ボックス（上の壁ぞい。左の角から並べる。2026-11-02 エイイチ）
    return dict(name="⑨ 大型店・郊外のゆったり型（厨房が右・入口が左下の角）", style="ゆったり", outer=dict(w=W, d=D),
                entrance=dict(side="bottom", a0=0.6, a1=3.6), rooms=rooms, walls=walls, toilet_doors=[td1, td2],
                dish_up=dish, robot_standby=sb, start=start, tables=t)


def run(pos, out):
    L = F.prepare(build_b() if pos == "b" else build(pos))
    v = F.check_rules(L)
    if v:
        for k, m in v:
            print("NG", k, m)
        return None
    ctx = {}
    res_a, err_a = F.analyze(L, F.SETTINGS["res"], ctx)
    res_b, err_b = F.analyze(L, F.SETTINGS["check_res"])
    v = err_a + [e for e in err_b if e not in err_a]
    if v:
        for k, m in v:
            print("NG", k, m)
        return None
    conv = [a["id"] for a, b in zip(res_a, res_b) if a["category"] != b["category"]]
    summ = F.summarize(L, res_a)
    nm = "p7_large_b" if pos == "b" else f"p6_large_{pos}"
    out.mkdir(parents=True, exist_ok=True)
    fig, ax = plt.subplots(figsize=(18, 11), dpi=110)
    F.draw(ax, L, res_a, summ, conv)
    fig.savefig(out / f"{nm}.png", bbox_inches="tight", facecolor="white")
    plt.close(fig)
    # サイトの平面図（serving-robot.html の planSvg・bigPlanSvg）と同じ形のデータ。画像は large_plan_images.py で描く
    ds = [r["dist"] for r in res_a if r.get("dist") is not None]
    plan = dict(w=W, d=D, outline=[[0, 0], [W, 0], [W, D], [0, D]],
                rooms=[[*r["rect"], r.get("kind", "back"), r["label"]] for r in L["rooms"]],
                walls=[w["rect"] for w in L["walls"]],
                tables=[[*F.fp(t), 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"]])
    info = dict(key=nm, name=L["name"], tables=len(L["tables"]), seats=summ["seats"],
                dist_m=[round(min(ds), 1), round(max(ds), 1)], dist_mean=summ["robot_dist_mean"], plan=plan)
    json.dump(info, open(out / f"{nm}_plan.json", "w", encoding="utf-8"), ensure_ascii=False)
    print("OK", nm, summ, "マス目の差", conv)
    return L, res_a, summ, conv, ctx


PUBLISH = {"p6_large_center": "center", "p7_large_b": "b"}   # サイトに載せる大型店の形（2026-11-02 エイイチ：⑧奥の真ん中・⑨入口が角）


def publish():
    """サイトに載せる大型店の形を public/sim/layouts/large/ に出す（今の6店の public/sim/layouts/ 直下は変えない）。
    作り方・確かめ・Unity の細かい形と地図は famires_v3 と同じ。全部が決まりを守ったときだけ書く"""
    import hashlib
    out = HERE.parent.parent / "public" / "sim" / "layouts" / "large"
    h = hashlib.sha256((F.generation_id() + (HERE / "large_store.py").read_text(encoding="utf-8")).encode())
    gen_id = "large-" + h.hexdigest()[:12]
    tmp = Path(tempfile.mkdtemp(prefix="large_"))
    allsum = []
    for nm, pos in PUBLISH.items():
        r = run(pos, tmp)
        if r is None:
            sys.exit(f"[NG] {nm}: 決まりに違反があるので、{out} には何も書いていない")
        L, res_a, summ, conv, ctx = r
        F.export(L, res_a, summ, conv, nm, tmp, gen_id)
        U = F.export_unity(L, res_a, ctx, nm, tmp, gen_id)
        vr = F.check_register_clear(U)
        if vr:
            sys.exit(f"[NG] {nm}: {vr}")
        allsum.append(dict(file=nm, status="OK", generation=gen_id, resolution_mismatch=conv, **summ))
    json.dump(allsum, open(tmp / "summary.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1)
    out.mkdir(parents=True, exist_ok=True)
    for f in tmp.rglob("*"):
        if f.is_file() and not f.name.endswith(".png") and not f.name.endswith("_plan.json"):
            dst = out / f.relative_to(tmp)
            dst.parent.mkdir(parents=True, exist_ok=True)
            f.replace(dst)
    print("published", out, gen_id)


if __name__ == "__main__":
    args = sys.argv[1:]
    if "--publish" in args:
        publish()
        sys.exit(0)
    out = Path(tempfile.gettempdir()) / "variants_large"   # 試作の図はリポジトリの外に出す（png は GitHub に入れない）
    if "--out" in args:
        i = args.index("--out")
        out = Path(args[i + 1])
        args = args[:i] + args[i + 2:]
    for pos in (args or list(DISH_POS)):
        run(pos, out)
