# -*- coding: utf-8 -*-
"""Spawn TNG eWallet with Frida native exit blockers."""
import subprocess
import sys
import time
from datetime import datetime
from pathlib import Path

import frida

PKG = "my.com.tngdigital.ewallet"
HERE = Path(__file__).resolve().parent
LOGS_DIR = HERE.parent / "logs" / "frida"
LOGS_DIR.mkdir(parents=True, exist_ok=True)
SCRIPT = HERE / "trace_tng_native_exit.js"
LOG = LOGS_DIR / ("tng_native_%s.log" % datetime.now().strftime("%Y%m%d_%H%M%S"))
ADB = r"C:\Users\Administrator\AppData\Local\Android\Sdk\platform-tools\adb.exe"
HOLD_SEC = 45


def on_message(message, data):
    mtype = message.get("type")
    if mtype == "send":
        line = message.get("payload")
    elif mtype == "log":
        line = message.get("payload", "")
    else:
        line = str(message)
    text = line if isinstance(line, str) else repr(line)
    print(text, flush=True)
    with open(LOG, "a", encoding="utf-8") as f:
        f.write(text + "\n")


def adb(*args):
    return subprocess.run([ADB, *args], capture_output=True, text=True)


def ensure_frida_server():
    out = adb("shell", "su", "-c", "pgrep -x frida-server")
    if out.stdout.strip():
        print("frida-server already running pid=%s" % out.stdout.strip())
        return
    print("starting frida-server ...")
    adb("shell", "su", "-c", "pkill -9 frida-server; true")
    # run in background via nohup-like
    subprocess.Popen(
        [ADB, "shell", "su", "-c", "/data/local/tmp/frida-server -D"],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
    )
    time.sleep(2)
    out = adb("shell", "su", "-c", "pgrep -x frida-server")
    if not out.stdout.strip():
        raise RuntimeError("frida-server failed to start")
    print("frida-server pid=%s" % out.stdout.strip())


def main():
    ensure_frida_server()
    adb("shell", "am", "force-stop", PKG)
    time.sleep(1)

    device = frida.get_usb_device(10)
    source = SCRIPT.read_text(encoding="utf-8")
    print("Spawning %s ..." % PKG)
    print("log=%s" % LOG)

    pid = device.spawn([PKG])
    session = device.attach(pid)
    script = session.create_script(source)
    script.on("message", on_message)
    script.load()
    print("script loaded, resume pid=%s" % pid)
    device.resume(pid)

    alive = 0
    for i in range(HOLD_SEC):
        time.sleep(1)
        # check process still alive
        out = adb("shell", "pidof", PKG)
        pids = out.stdout.strip()
        if not pids:
            print("DEAD after %ss" % (i + 1))
            break
        alive = i + 1
        if (i + 1) % 5 == 0:
            print("alive %ss pid=%s" % (alive, pids))
    else:
        print("STABLE %ss pid=%s" % (HOLD_SEC, adb("shell", "pidof", PKG).stdout.strip()))

    # dump activity focus
    focus = adb("shell", "dumpsys", "activity", "activities")
    for line in focus.stdout.splitlines():
        if "tngdigital" in line.lower() and (
            "mResumedActivity" in line
            or "topResumedActivity" in line
            or "UserLogin" in line
            or "SecurityError" in line
            or "Splash" in line
        ):
            print("ACT: " + line.strip())

    try:
        session.detach()
    except Exception:
        pass
    print("done alive=%ss log=%s" % (alive, LOG))
    return 0 if alive >= 15 else 1


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