import ctypes
from ctypes import wintypes
import time
import mmap
import struct
from PIL import Image

user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32

def attach_desktop():
    hwinsta = user32.OpenWindowStationW("WinSta0", False, 0x10000000)
    if hwinsta:
        user32.SetProcessWindowStation(hwinsta)
    hdesk = user32.OpenDesktopW("Default", 0, False, 0x10000000)
    if hdesk:
        user32.SetThreadDesktop(hdesk)

attach_desktop()

print("=== 1. FIND AND FOCUS POE2 WINDOW ===")
hwnd = user32.FindWindowW("POEWindowClass", None)
if not hwnd:
    hwnd = user32.FindWindowW(None, "Path of Exile 2")
if not hwnd:
    hwnd = 27726308
print(f"POE2 HWND: {hwnd} (0x{hwnd:08X})")

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

fg = user32.GetForegroundWindow()
print(f"Current Foreground Window: {fg} (Matches POE2: {fg == hwnd})")

print("\n=== 2. READ INITIAL IPC ===")
try:
    mm = mmap.mmap(-1, 48, 'AutoPOE2_VisualTool_v1')
    data = mm.read(48)
    magic, seq, cap, cur_before, flags, st, cam, fog, pid, err = struct.unpack('<IIffIIQQII', data)
    print(f"Before Scroll: cur_zoom={cur_before:.2f}x, cap={cap:.1f}x, status=0x{st:08X}, cam=0x{cam:016X}")
except Exception as e:
    print("IPC Read Error:", e)
    cur_before = 1.0

print("\n=== 3. SEND MOUSE SCROLL DOWN (ZOOM OUT) ===")
MOUSEEVENTF_WHEEL = 0x0800
WHEEL_DELTA = 120

# Send cursor to center of POE2 window first
rect = wintypes.RECT()
user32.GetWindowRect(hwnd, ctypes.byref(rect))
cx = (rect.left + rect.right) // 2
cy = (rect.top + rect.bottom) // 2
user32.SetCursorPos(cx, cy)
time.sleep(0.1)

# Scroll down 15 notches to zoom out significantly (e.g. +1.5x -> 2.5x)
for i in range(15):
    user32.mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -WHEEL_DELTA, 0)
    time.sleep(0.06)

print("Sent 15 mouse wheel scroll-down events.")
time.sleep(1.0)

print("\n=== 4. READ POST-SCROLL IPC ===")
try:
    mm.seek(0)
    data = mm.read(48)
    magic, seq, cap, cur_after, flags, st, cam, fog, pid, err = struct.unpack('<IIffIIQQII', data)
    print(f"After Scroll: cur_zoom={cur_after:.2f}x, cap={cap:.1f}x, status=0x{st:08X}, cam=0x{cam:016X}")
except Exception as e:
    print("IPC Read Error:", e)

print("\n=== 5. CAPTURE VERIFICATION SCREENSHOT ===")
w = rect.right - rect.left
h = rect.bottom - rect.top
print(f"Capture bounds: ({rect.left}, {rect.top}) -> ({rect.right}, {rect.bottom}), size: {w}x{h}")

desk_dc = user32.GetDC(0)
mem_dc = gdi32.CreateCompatibleDC(desk_dc)
bmp = gdi32.CreateCompatibleBitmap(desk_dc, w, h)
old_bmp = gdi32.SelectObject(mem_dc, bmp)

SRCCOPY = 0x00CC0020
ok = gdi32.BitBlt(mem_dc, 0, 0, w, h, desk_dc, rect.left, rect.top, SRCCOPY)
print(f"BitBlt success: {ok}")

class BITMAPINFOHEADER(ctypes.Structure):
    _fields_ = [
        ('biSize', wintypes.DWORD),
        ('biWidth', wintypes.LONG),
        ('biHeight', wintypes.LONG),
        ('biPlanes', wintypes.WORD),
        ('biBitCount', wintypes.WORD),
        ('biCompression', wintypes.DWORD),
        ('biSizeImage', wintypes.DWORD),
        ('biXPelsPerMeter', wintypes.LONG),
        ('biYPelsPerMeter', wintypes.LONG),
        ('biClrUsed', wintypes.DWORD),
        ('biClrImportant', wintypes.DWORD)
    ]

class BITMAPINFO(ctypes.Structure):
    _fields_ = [
        ('bmiHeader', BITMAPINFOHEADER),
        ('bmiColors', wintypes.DWORD * 3)
    ]

bmi = BITMAPINFO()
bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER)
bmi.bmiHeader.biWidth = w
bmi.bmiHeader.biHeight = -h
bmi.bmiHeader.biPlanes = 1
bmi.bmiHeader.biBitCount = 32
bmi.bmiHeader.biCompression = 0

buf_size = w * h * 4
raw_buf = ctypes.create_string_buffer(buf_size)
lines = gdi32.GetDIBits(mem_dc, bmp, 0, h, raw_buf, ctypes.byref(bmi), 0)

img = Image.frombuffer("RGBA", (w, h), raw_buf, "raw", "BGRA", 0, 1)
out_path = "captures/live_zoom_verified.png"
img.save(out_path)
print(f"Saved verification screenshot: {out_path} ({img.size})")

gdi32.SelectObject(mem_dc, old_bmp)
gdi32.DeleteObject(bmp)
gdi32.DeleteDC(mem_dc)
user32.ReleaseDC(0, desk_dc)

print("\n=== COMPLETED SUCCESSFULLY ===")
