#!/usr/bin/env python3
"""Batch-decompile Roblox scripts through the relay using an in-game resolver."""
import json, os, subprocess, sys, hashlib

TOKEN = "kaQlow93-f0LvZzf9d-V4kOLTmHuNCX_9VuhBpeV3P0"
RELAY = "/opt/ws-remote/relayctl.py"
OUTROOT = "/opt/ws-remote/scripts/soleezz/rivals/analysis"
TSV = "/tmp/opencode/dump_list2.tsv"
BATCH = 25

LUA = r'''
local paths = {%s}
local function resolve(path)
  local segs = string.split(path, ".")
  local cur
  for i, seg in ipairs(segs) do
    seg = string.gsub(seg, " $", "")
    if i == 1 then
      local ok, svc = pcall(game.GetService, game, seg)
      cur = (ok and svc) or game:FindFirstChild(seg) or game:FindFirstChild(seg .. " ")
    else
      cur = cur and cur:FindFirstChild(seg)
    end
    if not cur then return nil, seg end
  end
  return cur
end
for _, p in ipairs(paths) do
  local s, missing = resolve(p)
  if not s then
    print("===@MISS@|" .. p .. "|" .. tostring(missing))
  else
    local ok, src = pcall(decompile, s)
    if not ok then
      local ok2, bc = pcall(getscriptbytecode, s)
      print("===@ERR@|" .. p .. "|decompile:" .. tostring(src) .. "|bc=" .. (ok2 and #bc or -1))
    else
      print("===@BEGIN@|" .. p .. "|" .. #src)
      print(src)
      print("===@END@|" .. p)
    end
  end
end
'''


def safe(path):
    return "".join(c if (c.isalnum() or c in "-_") else "_" for c in path.replace(" ", "_").replace(".", "_"))


def main():
    lines = [l.rstrip("\n") for l in open(TSV) if l.strip()]
    os.makedirs("/tmp/opencode/batches", exist_ok=True)
    os.makedirs(OUTROOT, exist_ok=True)
    start = int(sys.argv[1]) if len(sys.argv) > 1 else 0
    end = int(sys.argv[2]) if len(sys.argv) > 2 else len(lines)
    lines = lines[start:end]
    total_written = 0
    for bi in range(0, len(lines), BATCH):
        chunk = lines[bi:bi + BATCH]
        paths = []
        for l in chunk:
            f = l.split("\t")
            if len(f) >= 4:
                paths.append(f[1])
        if not paths:
            continue
        lua_tbl = ",".join(json.dumps(p) for p in paths)
        script = LUA % lua_tbl
        sp = "/tmp/opencode/batches/b_%05d.lua" % bi
        open(sp, "w").write(script)
        out = "/tmp/opencode/batches/b_%05d.out" % bi
        with open(out, "w") as fh:
            subprocess.run(["python3", RELAY, "exec", "-f", sp, "--timeout", "300",
                            "--token", TOKEN], stdout=fh, stderr=subprocess.STDOUT)
        # split
        data = open(out, encoding="utf-8", errors="replace").read()
        cur = None
        buf = []
        idx = 0
        pref = os.environ.get("OUTPREFIX", "")
        for raw in data.split("\n"):
            line = raw
            if line.startswith("[print] "):
                line = line[8:]
            if line.startswith("===@BEGIN@|"):
                parts = line.split("|")
                cur = parts[1]
                buf = []
            elif line.startswith("===@END@|"):
                if cur:
                    p = pref + safe(cur) + ".lua"
                    open(p, "w").write("\n".join(buf))
                    total_written += 1
                    cur = None
            elif line.startswith("===@MISS@|") or line.startswith("===@ERR@|"):
                sys.stderr.write("BAD: " + line[:200] + "\n")
            elif cur is not None:
                buf.append(line)
        sys.stderr.write("batch %d done, written so far %d\n" % (bi, total_written))
    print("TOTAL", total_written)


if __name__ == "__main__":
    main()
