#!/usr/bin/env python3
"""Ensure the deployed launcher starts FIFA with the hook's WINEDLLOVERRIDES.

The hook ships as a `version.dll` proxy in the game directory, and Proton prefers a
local DLL over its own builtin ONLY when WINEDLLOVERRIDES names it. Launcher builds
before openfut-launcher c542415 apply `game_profile.env` but never that override, so
the hook silently never loads -- and with no hook there is no port rewrite, the
openfut.cfg the launcher just wrote is inert, and the client reaches EA's real Blaze
ports (production, via /etc/hosts) while looking like a healthy configured launch.

This writes the override into `game_profile.env`, which the deployed launcher DOES
apply, so it works without rebuilding. It is forward-compatible with the fixed
launcher: hook_dll_overrides() defers to a profile that already pins `version=`, so
the value set here simply wins and nothing conflicts.

    python3 scripts/client-hook-override.py show
    python3 scripts/client-hook-override.py apply
    python3 scripts/client-hook-override.py revert

Safety: the prior value (including its absence) is recorded to a sidecar before the
first mutation, so `revert` restores the real previous state rather than guessing;
every operation re-reads and prints the result; and it refuses to edit while the
launcher is running, because the launcher holds its config in memory and would write
the stale value straight back over ours.
"""
import json
import subprocess
import sys

CLIENT = "alex@10.10.0.105"
CFG = "/home/alex/.config/openfut-launcher/config.json"
SIDECAR = "/home/alex/.config/openfut-launcher/config.json.openfut-prev-dlloverrides"
KEY = "WINEDLLOVERRIDES"
HOOK = "version=n,b"
ABSENT = "<absent>"


def ssh(script):
    r = subprocess.run(["ssh", "-o", "BatchMode=yes", CLIENT, script],
                       capture_output=True, text=True, timeout=60)
    if r.returncode != 0:
        raise SystemExit(f"ssh failed ({r.returncode}): {r.stderr.strip()}")
    return r.stdout


def launcher_running():
    """comm is truncated by the kernel to 15 chars ("openfut-launche")."""
    out = ssh("for d in /proc/[0-9]*; do c=$(cat $d/comm 2>/dev/null); "
              "case \"$c\" in openfut-launche*) echo ${d#/proc/};; esac; done || true")
    return bool(out.strip())


def fifa_running():
    out = ssh("for d in /proc/[0-9]*; do "
              "[ \"$(cat $d/comm 2>/dev/null)\" = FIFA17.exe ] && echo ${d#/proc/}; "
              "done || true")
    return bool(out.strip())


def load():
    return json.loads(ssh(f'cat "{CFG}"'))


def env_of(d):
    return d.setdefault("game_profile", {}).setdefault("env", {})


def save(d):
    body = json.dumps(d, indent=2, sort_keys=True)
    ssh(f'cat > "{CFG}" <<\'EOF\'\n{body}\nEOF')


def show():
    d = load()
    cur = env_of(d).get(KEY, ABSENT)
    print(f"--- {CFG}")
    print(f"    game_profile.env[{KEY}] = {cur}")
    print(f"    hook active on launch   = {'YES' if 'version=' in cur else 'NO'}")
    side = ssh(f'cat "{SIDECAR}" 2>/dev/null || true').strip()
    print(f"    recorded previous value = {side or '(none recorded yet)'}")
    print(f"    launcher running        = {'YES' if launcher_running() else 'no'}")
    return cur


def guard():
    if fifa_running():
        raise SystemExit("REFUSING: a FIFA client is running; exit it first.")
    if launcher_running():
        raise SystemExit(
            "REFUSING: openfut-launcher is running. It holds its config in memory and\n"
            "would write the old value back over ours. Quit the launcher first.")


def apply_override():
    guard()
    d = load()
    env = env_of(d)
    prior = env.get(KEY, ABSENT)
    if not ssh(f'cat "{SIDECAR}" 2>/dev/null || true').strip():
        ssh(f'cat > "{SIDECAR}" <<\'EOF\'\n{prior}\nEOF')
        print(f"recorded previous value to {SIDECAR}: {prior}")
    # Preserve an unrelated override rather than clobbering it, and never double up.
    if prior != ABSENT and "version=" in prior:
        print(f"already pins version= ({prior}); leaving it alone")
        return show()
    env[KEY] = HOOK if prior == ABSENT else f"{prior};{HOOK}"
    save(d)
    after = env_of(load()).get(KEY, ABSENT)
    if "version=" not in after:
        raise SystemExit(f"VERIFY FAILED: {KEY} is {after!r}")
    return show()


def revert():
    guard()
    side = ssh(f'cat "{SIDECAR}" 2>/dev/null || true').strip()
    if not side:
        raise SystemExit(f"no recorded previous value at {SIDECAR}; refusing to guess")
    d = load()
    env = env_of(d)
    if side == ABSENT:
        env.pop(KEY, None)
    else:
        env[KEY] = side
    save(d)
    return show()


def main():
    if len(sys.argv) != 2 or sys.argv[1] not in ("show", "apply", "revert"):
        print(__doc__)
        return 2
    {"show": show, "apply": apply_override, "revert": revert}[sys.argv[1]]()
    return 0


if __name__ == "__main__":
    sys.exit(main())
