#!/usr/bin/env python3
import json
import re
from pathlib import Path

NEWSERV = Path.home() / ".local/share/github/psopeeps-newserv"
PEEPS_OUT = Path("site/generated/drops/peeps")
HARDCORE_OUT = Path("site/generated/drops/hardcore")

PEEPS_TABLES = {
    "v1": NEWSERV / "system/tables/rare-table-v1.json",
    "v2": NEWSERV / "system/tables/rare-table-v2.json",
    "v3": NEWSERV / "system/tables/rare-table-v3.json",
    "bb": NEWSERV / "system/tables/rare-table-v4.json",
}

HARDCORE_TABLES = {
    "bb": Path("source-drops/hardcore/rare-table-v4.json"),
}

def strip_json_comments(text):
    out = []
    in_str = False
    esc = False
    i = 0
    while i < len(text):
        c = text[i]
        n = text[i + 1] if i + 1 < len(text) else ""

        if in_str:
            out.append(c)
            if esc:
                esc = False
            elif c == "\\":
                esc = True
            elif c == '"':
                in_str = False
            i += 1
            continue

        if c == '"':
            in_str = True
            out.append(c)
            i += 1
            continue

        if c == "/" and n == "/":
            while i < len(text) and text[i] not in "\r\n":
                i += 1
            continue

        out.append(c)
        i += 1

    return "".join(out)

def quote_hex_numbers(text):
    return re.sub(r'(?<!["\w])0x[0-9A-Fa-f]+', lambda m: f'"{m.group(0)}"', text)


def remove_trailing_commas(text):
    out = []
    in_str = False
    esc = False
    i = 0

    while i < len(text):
        c = text[i]

        if in_str:
            out.append(c)
            if esc:
                esc = False
            elif c == "\\":
                esc = True
            elif c == '"':
                in_str = False
            i += 1
            continue

        if c == '"':
            in_str = True
            out.append(c)
            i += 1
            continue

        if c == ",":
            j = i + 1
            while j < len(text) and text[j] in " \t\r\n":
                j += 1
            if j < len(text) and text[j] in "}]":
                i += 1
                continue

        out.append(c)
        i += 1

    return "".join(out)

def load_newserv_jsonish(path):
    text = path.read_text(encoding="utf-8", errors="replace")
    text = strip_json_comments(text)
    text = quote_hex_numbers(text)
    text = remove_trailing_commas(text)
    return json.loads(text)

def normalize_item_code(value):
    if isinstance(value, str) and value.startswith("0x"):
        return "0x" + value[2:].upper()
    if isinstance(value, int):
        return f"0x{value:06X}"
    return str(value)

def flatten_table(version, table):
    rows = []

    for game_mode, episodes in table.items():
        if not isinstance(episodes, dict):
            continue
        for episode, difficulties in episodes.items():
            if not isinstance(difficulties, dict):
                continue
            for difficulty, section_ids in difficulties.items():
                if not isinstance(section_ids, dict):
                    continue
                for section_id, sources in section_ids.items():
                    if not isinstance(sources, dict):
                        continue
                    for source, drops in sources.items():
                        if not isinstance(drops, list):
                            continue
                        for drop in drops:
                            if not isinstance(drop, list) or len(drop) < 2:
                                continue

                            rows.append({
                                "version": version,
                                "mode": str(game_mode),
                                "episode": str(episode),
                                "difficulty": str(difficulty),
                                "section_id": str(section_id),
                                "source": str(source),
                                "rate": str(drop[0]),
                                "item_code": normalize_item_code(drop[1]),
                                "item": str(drop[2]) if len(drop) >= 3 and drop[2] else "",
                            })

    return rows

def write_group(mode, label, tables, out_dir):
    out_dir.mkdir(parents=True, exist_ok=True)

    index = {
        "mode": mode,
        "label": label,
        "tables": [],
    }

    labels = {"v1": "V1", "v2": "V2", "v3": "V3", "bb": "BB"}

    for version, src in tables.items():
        table = load_newserv_jsonish(src)
        rows = flatten_table(version, table)

        out_name = f"{version}.json"
        out_path = out_dir / out_name
        out_path.write_text(json.dumps(rows, indent=2, sort_keys=True) + "\n")

        index["tables"].append({
            "version": version,
            "label": labels[version],
            "path": out_name,
            "rows": len(rows),
        })

        print(f"{mode} {version}: {len(rows)} rows -> {out_path}")

    index_path = out_dir / "index.json"
    index_path.write_text(json.dumps(index, indent=2, sort_keys=True) + "\n")
    print(f"{mode} index -> {index_path}")

def main():
    write_group("peeps", "Peeps", PEEPS_TABLES, PEEPS_OUT)
    write_group("hardcore", "Hardcore", HARDCORE_TABLES, HARDCORE_OUT)

if __name__ == "__main__":
    main()
