# -*- coding: utf-8 -*-
"""在庫・配布DB(inventory.json) ビルダ。board段の共通関数を import 再利用。"""
import json, os, importlib.util

BASE = os.path.dirname(os.path.abspath(__file__))
# board段スクリプトから共通関数・ジオコードを読み込む
spec = importlib.util.spec_from_file_location("bb", os.path.join(BASE, "_board_lib.py"))
bb = importlib.util.module_from_spec(spec)
spec.loader.exec_module(bb)

resolve_coords = bb.resolve_coords
ADDR = bb.ADDR
boards = bb.boards
VOLS_BOARD = bb.VOLS_BOARD
save_cache = bb.save_cache
CACHE = bb.CACHE

FOOD = [
    ("おしおりーぶ","宮内",[100,0,0,0,0,None]),
    ("谷中ビアホール","宮内",[25,25,25,25,25,None]),
    ("花重谷中茶屋","宮内",[51,0,50,718,175,None]),
    ("筆や","宮内",[0,0,45,0,0,None]),
    ("SAGITTAIRE","宮内",[0,0,75,0,0,None]),
    ("BUZZED LAMB BREWING","宮内",[0,0,50,0,0,None]),
    ("ヤナカアパートメントストア spiq","宮内",[0,0,25,0,0,None]),
    ("ヤナカアパートメントストア SMPL café","宮内",[0,0,75,0,0,None]),
    ("madei","宮内",[0,0,0,0,25,None]),
    ("Mrs.Charlotte LA MAISON","宮内",[0,0,0,0,25,None]),
    ("feb's coffee ＆ scone","宮内",[0,0,0,0,25,None]),
    ("喫茶 清浄無垢","満田",[25,25,25,100,25,None]),
    ("酒処 侘助","満田",[0,25,25,25,25,None]),
    ("浅草鳥きち","満田",[0,25,25,25,50,None]),
    ("レオニダス浅草店 Cafe Rion","満田",[0,25,25,25,50,None]),
    ("中国菜～道 dao～","満田",[0,25,25,25,50,None]),
    ("さけ処 川セ美","満田",[0,25,25,25,50,None]),
    ("浅草展望カフェ Cafe Rion","満田",[0,0,0,0,50,None]),
    ("チーズ料理専門店 チーズ谷","浅川",[0,50,50,50,25,None]),
    ("とんかつ とん将","浅川",[0,25,25,25,25,None]),
    ("楽亀","浅川",[0,25,25,25,25,None]),
    ("四川料理 蜀香坊","浅川",[0,25,25,25,25,None]),
    ("とんかつ とん平","浅川",[0,25,25,25,25,None]),
    ("U BLUE","杉本",[0,25,25,25,25,None]),
    ("ビストロ酒場5感","杉本",[0,25,25,25,25,None]),
    ("珈琲の店デン","杉本",[0,25,25,25,25,None]),
    ("CAFÉ＆BAR ROSSONERO","杉本",[0,25,25,25,25,None]),
    ("CAFE BEVANDARIA","杉本",[0,25,50,50,25,None]),
    ("江戸前煮干 中華そば きみはん 総本店","杉本",[0,25,25,25,25,None]),
    ("鮨 くり田","杉本",[0,5,25,25,25,None]),
    ("縁","杉本",[0,0,0,0,50,None]),
    ("根津 松吉","加藤",[0,0,0,0,25,None]),
    ("アライ軒","加藤",[0,0,0,0,25,None]),
    ("CANNONBALL DINER","加藤",[0,10,50,25,0,None]),
    ("オオイリヤ","加藤",[0,30,30,25,25,None]),
    ("龍一吟","加藤",[0,25,25,30,25,None]),
    ("はつね","加藤",[0,5,10,5,25,None]),
    ("サウナセンター鶯谷本店","加藤",[0,25,25,50,25,None]),
    ("炭火焼18","加藤",[0,30,30,25,25,None]),
    ("カフェバーミヤミ","加藤",[0,5,30,30,25,None]),
    ("Dining Bar 第三基地","加藤",[0,5,25,25,25,None]),
    ("カラオケMIX BAR 第四基地","加藤",[0,25,25,25,25,None]),
    ("タラレバゴルフ＆バー","加藤",[0,5,50,50,25,None]),
    ("居酒屋 関所","加藤",[0,25,0,25,25,None]),
    ("合羽橋 栃木屋","加藤",[0,30,75,75,30,None]),
    ("焼豚 大井川","加藤",[0,0,0,10,0,None]),
    ("LUPI COFFEE","阿部",[0,0,0,50,3,None]),
    ("COLORE","阿部",[0,0,0,25,3,None]),
    ("ROUTE BOOKS","阿部",[0,0,0,200,51,None]),
    ("American Diner ANDRA","阿部",[0,0,0,50,5,None]),
    ("Guruastu","阿部",[0,0,0,100,25,None]),
    ("Dito","阿部",[0,0,50,100,50,None]),
    ("歌謡曲カフェLover’s","阿部",[150,100,200,200,200,None]),
    ("よーかんちゃん","阿部",[50,0,50,25,25,None]),
    ("あんみつ あいば","阿部",[50,0,50,50,50,None]),
    ("ダンスホール新世紀","阿部",[0,200,200,100,100,None]),
    ("大弘（中華店）","阿部",[0,0,25,50,25,None]),
    ("海老屋","阿部",[0,0,0,0,25,None]),
    ("十和田（浅草蕎麦屋）おかみさん会","阿部",[0,0,0,50,50,None]),
    ("炭火焼きと純米酒さとうともや","廣瀬",[0,0,0,0,25,None]),
    ("徳岡官兵衛茶舗","廣瀬",[0,0,0,0,25,None]),
    ("ミカワシマバル スズナリ","廣瀬",[0,0,0,0,25,None]),
]

NONFOOD = [
    ("Soy＆Co 1879","加藤",[0,5,10,25,5,None]),
    ("Stay SAKURA Tokyo 江戸乃舞","加藤",[0,0,0,25,0,None]),
    ("根岸中央整骨院","加藤",[0,3,0,0,8,None]),
    ("本間商店","加藤",[0,0,0,0,30,None]),
    ("サウナ大泉","加藤",[0,0,0,0,25,None]),
    ("富士大泉","加藤",[0,0,0,0,25,None]),
    ("はぎわら青果","加藤",[0,0,0,0,25,None]),
    ("鮫の歯","宮内",[0,0,50,0,0,None]),
    ("ヤナカアパートメントストア Amazing Moments Yanaka","宮内",[0,0,75,25,25,None]),
    ("定期購読","宮内",[0,0,0,17,19,None]),
    ("店舗B（管理物件）","宮内",[34,0,0,136,106,None]),
    ("旧池田邸（管理物件）","宮内",[0,0,0,113,45,None]),
    ("城北信金(管理物件)","宮内",[29,0,13,51,10,None]),
    ("美容室（管理物件）","宮内",[32,0,0,38,17,None]),
    ("旧種村邸（管理物件）","宮内",[0,0,0,48,0,None]),
    ("言問宿（管理物件）","宮内",[113,13,14,334,114,None]),
    ("言問茶屋（管理物件）","宮内",[84,4,15,311,124,None]),
    ("旧伊達邸 （管理物件）","宮内",[15,15,0,29,25,None]),
    ("上野観光案内所","宮内",[0,0,0,55,100,None]),
    ("須藤さん","宮内",[0,0,0,0,5,None]),
    ("東京観光情報センター 京成上野","宮内",[0,0,0,125,100,None]),
    ("リズムネイション","宮内",[0,0,0,0,50,None]),
    ("ポスティング","宮内",[0,0,0,0,1500,None]),
    ("国立国会図書館（関西館含む）","金井",[3,3,3,3,3,None]),
    ("二木商会・二木の菓子","阿部",[0,0,0,400,277,None]),
    ("清水観音堂","阿部",[200,100,100,350,200,None]),
    ("寛永寺根本中堂","阿部",[300,200,250,250,302,None]),
    ("小野照崎神社","阿部",[100,100,200,300,302,None]),
    ("元三島神社","阿部",[100,100,50,100,102,None]),
    ("三島神社","阿部",[0,0,0,25,25,None]),
    ("根津神社","阿部",[50,0,0,0,0,None]),
    ("浅草神社","阿部",[50,0,0,0,0,None]),
    ("間宮クリーニング","阿部",[0,0,0,0,25,None]),
    ("ホテルイースト","阿部",[0,0,0,0,50,None]),
    ("BIG BEST（バイク屋）","阿部",[0,50,50,150,25,None]),
    ("杉浦（東上野・倫理）","阿部",[0,0,25,50,25,None]),
    ("八百屋・内田","阿部",[0,0,25,50,25,None]),
    ("カマヤ（ガソリンスタンド）","阿部",[0,0,100,50,25,None]),
    ("真源寺","阿部",[0,0,200,50,25,None]),
    ("芹沢・保坂","阿部",[0,0,75,100,0,None]),
    ("浅草倫理法人会","阿部",[0,200,200,100,25,None]),
    ("保坂先生","阿部",[0,100,100,25,5,None]),
    ("新井（床屋）","阿部",[0,0,0,50,50,None]),
    ("浅草見番","阿部",[50,50,50,25,0,None]),
    ("尾藤川柳先生","阿部",[0,0,200,0,0,None]),
    ("浅草商店街連合会","阿部",[0,400,50,100,25,None]),
    ("宝飾店ジュフロア","阿部",[50,50,100,250,102,None]),
    ("東京新聞下町支局","阿部",[20,20,10,10,10,None]),
    ("石山（合羽橋入口）","阿部",[5,15,25,25,5,None]),
    ("合鍵のプラスワン","阿部",[25,50,50,50,52,None]),
    ("ジェイパーク上野","阿部",[25,25,25,25,25,None]),
    ("東京国際通り振興会","阿部",[0,400,25,25,100,None]),
    ("蔵前商店街","阿部",[0,400,100,200,250,None]),
    ("奥浅草観光協会","阿部",[0,400,50,200,301,None]),
    ("一葉商店街","阿部",[0,50,25,25,52,None]),
    ("上野桜木町会","阿部",[0,100,25,10,5,None]),
    ("桜守の会","阿部",[0,800,0,50,2000,None]),
    ("藝大部屋","阿部",[0,125,50,50,50,None]),
    ("阿部・手渡し配布・ポステイング・郵送","阿部",[1253,187,790,550,380,None]),
    ("猿若町会・小竹会長","阿部",[0,0,0,0,25,None]),
    ("フジトウ商事（猿若町会）","阿部",[0,0,0,0,25,None]),
    ("美容室ナチュレイ","阿部",[0,50,50,200,75,None]),
    ("根岸三平堂","阿部",[0,0,0,150,100,None]),
    ("下町ミュージアム＋吉田屋","阿部",[0,0,0,150,200,None]),
    ("日鉄興和不動産","石井",[0,0,0,0,25,None]),
    ("手塚先生","石井",[0,0,0,0,5,None]),
    ("きらぼし銀行","石井",[0,0,0,0,5,None]),
    ("第一歓信","石井",[0,0,0,0,25,None]),
    ("第一興商","石井",[0,0,0,0,100,None]),
    ("ホテルHAKU","杉本",[0,0,0,0,25,None]),
    ("セレナ","",[0,0,0,0,50,None]),
    ("上野桜木アーティストスクール","宮内",[0,0,0,0,None,None]),
]

VOLS_INV = ["vol10","vol11","vol12","vol13","vol14","vol15"]
NOTE_OVERRIDE = {
    "旧池田邸（管理物件）": "解体のため補充停止",
    "旧種村邸（管理物件）": "外壁工事のため補充不可",
    "旧伊達邸 （管理物件）": "解体のため補充停止",
    "上野桜木アーティストスクール": "Vol.15から発送",
}

placements = []
print("=== INVENTORY geocoding ===")
for cat, rows in (("飲食店", FOOD), ("飲食店以外", NONFOOD)):
    for name, tantou, cl in rows:
        addr = ADDR.get(name)
        lat, lng, sid, src = resolve_coords(name, addr)
        counts = {}
        total = 0
        for i, v in enumerate(VOLS_INV):
            counts[v] = cl[i]
            if cl[i]:
                total += cl[i]
        placements.append({
            "location": name, "category": cat,
            "tantou": tantou if tantou else None,
            "address": addr if addr else None,
            "lat": lat, "lng": lng, "geocode": src, "storeId": sid,
            "counts": counts, "total": total,
            "note": NOTE_OVERRIDE.get(name, ""),
        })

byIssue = []
for v in VOLS_INV:
    food_t = sum((p["counts"][v] or 0) for p in placements if p["category"]=="飲食店")
    non_t  = sum((p["counts"][v] or 0) for p in placements if p["category"]=="飲食店以外")
    board_t = sum((b["counts"].get(v) or 0) for b in boards)
    byIssue.append({"vol": int(v.replace("vol","")), "total": food_t+non_t+board_t,
                    "飲食": food_t, "非飲食": non_t, "ボード": board_t})

byLocationTop = sorted(
    [{"location": p["location"], "category": p["category"], "total": p["total"]} for p in placements],
    key=lambda x: x["total"], reverse=True)

STOCK_VOLS = ["vol1","vol2","vol3","vol4","vol5","vol6","tokubetsu",
              "vol7","vol8","vol9","vol10","vol11","vol12","vol13","vol14","map"]
STOCK_ROWS = {
    "本社":     [163,16,153,156,79,89,None,51,118,34,12,43,32,90,100,50],
    "言問宿1F":  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    "大日印刷":  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    "旧富田邸":  [0,0,0,0,0,0,0,529,800,728,1396,2055,44,0,0,250],
    "阿部所持":  [1,1,1,1,1,1,1,6,5,20,47,3,61,42,20,0],
}
stock = []
for loc, vals in STOCK_ROWS.items():
    byVol = {STOCK_VOLS[i]: vals[i] for i in range(len(STOCK_VOLS))}
    stock.append({"location": loc, "byVol": byVol, "total": sum(v for v in vals if v)})

stockTotalByVol = {}
for i, v in enumerate(STOCK_VOLS):
    stockTotalByVol[v] = sum((STOCK_ROWS[loc][i] or 0) for loc in STOCK_ROWS)

inv_meta = {
    "title": "言問散歩 在庫・配布数DB",
    "purpose": "号ごと・場所ごとの配本冊数と在庫の集計マスター。アプリ『在庫』タブが読む。byIssue/byLocationTopはグラフ用集計値。",
    "sources": [
        "在庫/設置数 正本スプレッドシート fileId 1rhKwpQVhNGhPeGdlklZjfF4rCKBM12ex",
        " ブロック① 設置冊数(飲食店) Vol.10-15／② 設置冊数(飲食店以外) Vol.10-15",
        " ブロック⑤ 在庫(本社/言問宿1F/大日印刷/旧富田邸/阿部所持 × Vol.1-14＋マップ)",
        "ボード配本=board.json(ブロック③)を参照",
    ],
    "geocoding": "国土地理院 AddressSearch + meiten-master.json 既存座標流用。台東中心域チェック。住所未取得=null。",
    "volsCovered": "配布=Vol.10〜15（Vol.15は配本前で全空欄）。在庫=Vol.1〜14＋特別編集号＋マップ。",
    "fabricationNote": "GR19準拠。全数値はスプレッドシート実値。空欄=null。号横断の単純合計のみ算出（推計なし）。",
    "stockSnapshot": "在庫の旧富田邸スナップショット日付=2026/5/18（スプレッドシート注記）。",
    "updated": "2026-06-07",
}

inv_out = {"_meta": inv_meta, "placements": placements, "byIssue": byIssue,
           "byLocationTop": byLocationTop, "stock": stock, "stockTotalByVol": stockTotalByVol}
json.dump(inv_out, open(os.path.join(BASE, "inventory.json"), "w", encoding="utf-8"),
          ensure_ascii=False, indent=2)
save_cache(CACHE)

n_geo_inv = sum(1 for p in placements if p["lat"] is not None)
n_pending = sum(1 for p in placements if p["lat"] is None)
print()
print("inventory.json:", len(placements), "placements / geocoded", n_geo_inv, "/ pending", n_pending)
print("byIssue:", [(x["vol"], x["total"], x["飲食"], x["非飲食"], x["ボード"]) for x in byIssue])
print("top5:", [(x["location"], x["total"]) for x in byLocationTop[:5]])
print("stockTotalByVol:", stockTotalByVol)
print("pending locations:", [p["location"] for p in placements if p["lat"] is None])
