#!/usr/bin/env python3
"""Extract SAND loot/drop tables from the two Odin-binary LootTablesConfig assets.

Decodes conf_worldLootTablesStormConfig + conf_worldLootTablesVoyageConfig (Odin
SerializedFormat=0 Binary) via odin_read, flattens to a clean dict:
  { region: { lootTableId: [ {itemBlueprint, countMin, countMax, ...}, ... ] } }
Writes extracted/loot_tables.json (+ reports any unexpected fields / coverage).
"""
import os, sys, json
import odin_read

EX = "/home/downloadpizza/sand_tools/extracted"
REGIONS = {
    "Storm":  "conf_worldLootTablesStormConfig.odin.bin",
    "Voyage": "conf_worldLootTablesVoyageConfig.odin.bin",
}

def odin_list(node):
    """Unwrap an Odin List<T> node -> python list of elements."""
    if node is None: return []
    if isinstance(node, list): return node
    items = node.get("$items", [])
    # List nodes serialize as one inner array: $items == [[...elements...]]
    out = []
    for chunk in items:
        if isinstance(chunk, list): out.extend(chunk)
        else: out.append(chunk)
    return out

def main():
    result = {}
    extra_fields = set()
    item_ids = set()
    for region, fn in REGIONS.items():
        path = os.path.join(EX, fn)
        data = open(path, "rb").read()
        parsed = odin_read.parse(data)
        assert parsed["consumed"] == parsed["total"], f"{region}: incomplete parse"
        tables = odin_list(parsed["roots"]["_lootTables"])
        region_out = {}
        for t in tables:
            tid = t.get("lootTableId")
            items = odin_list(t.get("items"))
            rows = []
            for it in items:
                row = {k: v for k, v in it.items() if k != "$type"}
                for k in row:
                    if k not in ("itemBlueprint", "countMin", "countMax"):
                        extra_fields.add(k)
                if "itemBlueprint" in row:
                    item_ids.add(row["itemBlueprint"])
                rows.append(row)
            region_out[tid] = rows
        result[region] = region_out
        print(f"{region}: {len(region_out)} loot tables, "
              f"{sum(len(v) for v in region_out.values())} drop rows")
    out = os.path.join(EX, "loot_tables.json")
    json.dump(result, open(out, "w"), indent=1, ensure_ascii=False)
    print(f"\nwrote {out}")
    print(f"unique item blueprints referenced: {len(item_ids)}")
    if extra_fields:
        print(f"NOTE extra (non count) fields present: {sorted(extra_fields)}")
    # how many drop-table item ids are NOT in our authoritative item registry?
    reg_path = os.path.join(EX, "items_registry.json")
    if os.path.exists(reg_path):
        reg = set(json.load(open(reg_path))["items"].keys())
        unknown = sorted(i for i in item_ids if i not in reg)
        print(f"item blueprints not in items_registry: {len(unknown)}")
        for u in unknown[:40]:
            print("   ", u)

if __name__ == "__main__":
    main()
