"""RE verify - Kiem tra dia chi neo phase_1 hien co on khong (ca 3 PID lien quan).
ONLY ReadProcessMemory (VM_READ), never write. Requires Admin.
Usage: python verify_anchor.py [pid]   (PID gan dung nhat la 87600)
Output: logs/re_npc_list/verify_pid<PID>.txt
"""
from __future__ import annotations

import ctypes
import os
import subprocess
import time
from ctypes import wintypes

LOG_DIR = r"C:\Projects\JX\logs\re_npc_list"
os.makedirs(LOG_DIR, exist_ok=True)

k32 = ctypes.WinDLL("kernel32", use_last_error=True)
PROCESS_VM_READ = 0x0010
PROCESS_QUERY_INFORMATION = 0x0400

k32.OpenProcess.restype = wintypes.HANDLE
k32.OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
k32.ReadProcessMemory.restype = wintypes.BOOL
k32.ReadProcessMemory.argtypes = [wintypes.HANDLE, wintypes.LPCVOID, wintypes.LPVOID,
                                  ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)]
k32.CloseHandle.argtypes = [wintypes.HANDLE]

STATIC_NAME = 0x006DEC44
STATIC_LEVEL = 0x006DEC66
STATIC_MAP = 0x006966CC
COORD_OFF = 0x270

TARGET = 0x105AF774


def read_mem(h, addr, size):
    buf = (ctypes.c_char * size)()
    br = ctypes.c_size_t(0)
    if not k32.ReadProcessMemory(h, ctypes.c_void_p(addr), buf, size, ctypes.byref(br)):
        return None
    return bytes(buf)[: br.value]


def main():
    import sys
    import struct
    pids = []
    for a in sys.argv[1:]:
        try:
            pids.append(int(a))
        except ValueError:
            pass
    if not pids:
        pids = [87600]
    for pid in pids:
        log_path = os.path.join(LOG_DIR, f"verify_pid{pid}.txt")
        lines = []

        def log(msg):
            s = f"[{time.strftime('%H:%M:%S')}] {msg}"
            print(s, flush=True)
            lines.append(s)
            with open(log_path, "w", encoding="utf-8") as f:
                f.write("\n".join(lines))

        log(f"===== VERIFY PID {pid} target=0x{TARGET:X} =====")
        try:
            import psutil
            p = psutil.Process(pid)
            log(f"proc={p.name()} started={time.strftime('%H:%M', time.localtime(p.create_time()))}")
        except Exception as ex:
            log(f"psutil: {ex}")
        h = k32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
        if not h:
            log(f"OpenProcess FAILED err={ctypes.get_last_error()}")
            continue
        try:
            nmB = read_mem(h, STATIC_NAME, 32)
            lvB = read_mem(h, STATIC_LEVEL, 4)
            mpB = read_mem(h, STATIC_MAP, 8)
            name = nmB.split(b"\x00", 1)[0].decode("latin1", "replace") if nmB else "?"
            log(f"name='{name}' level={int.from_bytes(lvB,'little') if lvB else -1} "
                f"mapId={int.from_bytes(mpB[:4],'little') if mpB else -1}")
            for i in range(4):
                raw = read_mem(h, TARGET - 0x28, 0x28 + 0x280)
                if not raw or len(raw) < 0x28 + 0x280:
                    log(f"[{i}] KHONG doc duoc (fail)")
                    break

                def at(rel):
                    return struct.unpack("<i", raw[0x28 + rel:0x28 + rel + 4])[0]

                hp, s1, v100, s2 = at(-24), at(-20), at(-16), at(-4)
                sta, ms = at(0), at(4)
                cx, cy = at(COORD_OFF), at(COORD_OFF + 4)
                sig_ok = 0 <= s1 < 200 and v100 == 100 and 0 <= s2 < 200
                log(f"[{i}] hp={hp} sta={sta}/{ms} sig=({s1},{v100},{s2}) sig_ok={sig_ok} "
                    f"coords=({cx},{cy}) HUD=({round(cx/256)},{round(cy/512)})")
                if i < 3:
                    time.sleep(4)
        except Exception as ex:
            import traceback
            log(f"EXCEPTION: {ex}")
            log(traceback.format_exc())
        finally:
            k32.CloseHandle(h)
            log(f"===== PID {pid} done =====")
    print("ALL DONE", flush=True)


if __name__ == "__main__":
    main()
