import time
import ctypes
from ctypes import wintypes
import struct
import sys

log_fp = open(r"c:\Projects\AutoPOE2\scratch\skill_q.log", "w", encoding="utf-8")
old_print = print
def print(*args, **kwargs):
    old_print(*args, **kwargs)
    old_print(*args, **kwargs, file=log_fp)
    log_fp.flush()

user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32

ULONG_PTR = ctypes.c_uint64

class KEYBDINPUT(ctypes.Structure):
    _fields_ = [
        ('wVk', wintypes.WORD),
        ('wScan', wintypes.WORD),
        ('dwFlags', wintypes.DWORD),
        ('time', wintypes.DWORD),
        ('dwExtraInfo', ULONG_PTR),
    ]

class MOUSEINPUT(ctypes.Structure):
    _fields_ = [
        ('dx', wintypes.LONG),
        ('dy', wintypes.LONG),
        ('mouseData', wintypes.DWORD),
        ('dwFlags', wintypes.DWORD),
        ('time', wintypes.DWORD),
        ('dwExtraInfo', ULONG_PTR),
    ]

class HARDWAREINPUT(ctypes.Structure):
    _fields_ = [
        ('uMsg', wintypes.DWORD),
        ('wParamL', wintypes.WORD),
        ('wParamH', wintypes.WORD),
    ]

class INPUT_UNION(ctypes.Union):
    _fields_ = [
        ('mi', MOUSEINPUT),
        ('ki', KEYBDINPUT),
        ('hi', HARDWAREINPUT),
    ]

class INPUT(ctypes.Structure):
    _anonymous_ = ('u',)
    _fields_ = [
        ('type', wintypes.DWORD),
        ('u', INPUT_UNION),
    ]

def send_key_sendinput(vk, scan):
    inp = INPUT(type=1)
    inp.ki.wVk = vk
    inp.ki.wScan = scan
    inp.ki.dwFlags = 0 # VK
    r1 = user32.SendInput(1, ctypes.byref(inp), ctypes.sizeof(INPUT))
    time.sleep(0.08)
    inp.ki.dwFlags = 2 # KEYEVENTF_KEYUP
    r2 = user32.SendInput(1, ctypes.byref(inp), ctypes.sizeof(INPUT))
    return r1, r2

def send_key_scancode(scan):
    inp = INPUT(type=1)
    inp.ki.wVk = 0
    inp.ki.wScan = scan
    inp.ki.dwFlags = 0x0008 # KEYEVENTF_SCANCODE
    r1 = user32.SendInput(1, ctypes.byref(inp), ctypes.sizeof(INPUT))
    time.sleep(0.08)
    inp.ki.dwFlags = 0x0008 | 0x0002 # KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP
    r2 = user32.SendInput(1, ctypes.byref(inp), ctypes.sizeof(INPUT))
    return r1, r2

def send_keybd_event(vk, scan):
    user32.keybd_event(vk, scan, 0, 0)
    time.sleep(0.08)
    user32.keybd_event(vk, scan, 2, 0)

def main():
    try:
        hwinsta = user32.OpenWindowStationW("WinSta0", False, 0x10000000)
        if hwinsta: user32.SetProcessWindowStation(hwinsta)
        hdesk = user32.OpenDesktopW("Default", 0, False, 0x10000000)
        if hdesk: user32.SetThreadDesktop(hdesk)
    except Exception as e:
        print(f"Desktop error: {e}")

    hwnd = user32.FindWindowW("POEWindowClass", None)
    if not hwnd: hwnd = user32.FindWindowW(None, "Path of Exile 2")
    print(f"HWND: {hwnd}")
    if not hwnd: return

    user32.ShowWindow(hwnd, 9)
    user32.SetForegroundWindow(hwnd)
    user32.BringWindowToTop(hwnd)
    time.sleep(0.5)

    pid = 43084
    h_proc = kernel32.OpenProcess(0x0410, False, pid)
    life_addr = 0x2AF791A03E8
    mana_addr = life_addr + 0x420

    def read_mana():
        if not h_proc: return 0
        buf = ctypes.create_string_buffer(4)
        br = ctypes.c_size_t(0)
        kernel32.ReadProcessMemory(h_proc, ctypes.c_void_p(mana_addr), buf, 4, ctypes.byref(br))
        return struct.unpack('I', buf.raw)[0] if br.value == 4 else 0

    mana_start = read_mana()
    print(f"Mana before test: {mana_start}")

    # Method 1: keybd_event 'Q' (VK 0x51, scan 0x10)
    print("\n--- Method 1: keybd_event 'Q' ---")
    send_keybd_event(0x51, 0x10)
    time.sleep(0.6)
    mana_m1 = read_mana()
    print(f"Mana after keybd_event: {mana_m1} (Delta: {mana_m1 - mana_start})")

    # Method 2: SendInput VK 'Q'
    print("\n--- Method 2: SendInput VK 'Q' ---")
    r1, r2 = send_key_sendinput(0x51, 0x10)
    time.sleep(0.6)
    mana_m2 = read_mana()
    print(f"SendInput VK res=({r1},{r2}) | Mana after: {mana_m2} (Delta: {mana_m2 - mana_m1})")

    # Method 3: SendInput Scancode 'Q' (0x10)
    print("\n--- Method 3: SendInput Scancode 'Q' (0x10) ---")
    r1, r2 = send_key_scancode(0x10)
    time.sleep(0.6)
    mana_m3 = read_mana()
    print(f"SendInput Scancode res=({r1},{r2}) | Mana after: {mana_m3} (Delta: {mana_m3 - mana_m2})")

    # Capture screen
    sys.path.insert(0, r"C:\Projects\AutoPOE2")
    from tools.autonomous_map_runner import ScreenCapturerGDI
    c = ScreenCapturerGDI()
    c.capture(r"C:\Projects\AutoPOE2\captures\test_skill_q_after.png")

    if h_proc: kernel32.CloseHandle(h_proc)
    print("\nDone.")

if __name__ == "__main__":
    main()
