import os
import sys
import time
import math
import ctypes
from ctypes import wintypes

sys.path.insert(0, r"c:\Projects\AutoPOE2")

from src.common.win32_window import attach_to_default_desktop, find_poe2_window, get_client_rect
from src.common.virtual_display_manager import capture_virtual_display
from tools.autonomous_mapping_coordinator import AutonomousMappingCoordinator

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

# 1. Attach thread to Default desktop
attach_to_default_desktop()
hwnd = find_poe2_window()
if not hwnd:
    print("❌ PoE2 window not found!")
    sys.exit(1)

print(f"🎯 Target PoE2 HWND: {hex(hwnd)}")

# Define SendInput structures
class KEYBDINPUT(ctypes.Structure):
    _fields_ = [
        ("wVk", wintypes.WORD),
        ("wScan", wintypes.WORD),
        ("dwFlags", wintypes.DWORD),
        ("time", wintypes.DWORD),
        ("dwExtraInfo", ctypes.c_ulong),
    ]

class INPUT_I(ctypes.Union):
    _fields_ = [("ki", KEYBDINPUT)]

class INPUT(ctypes.Structure):
    _fields_ = [("type", wintypes.DWORD), ("i", INPUT_I)]

INPUT_KEYBOARD = 1
KEYEVENTF_SCANCODE = 0x0008
KEYEVENTF_KEYUP = 0x0002
VK_MENU = 0x12
VK_W = 0x57
SC_W = 0x11
VK_A = 0x41
SC_A = 0x1E
VK_S = 0x53
SC_S = 0x1F
VK_D = 0x44
SC_D = 0x20

def send_key_down(vk, sc):
    inp = (INPUT * 2)()
    inp[0].type = INPUT_KEYBOARD
    inp[0].i.ki.wScan = sc
    inp[0].i.ki.dwFlags = KEYEVENTF_SCANCODE
    inp[1].type = INPUT_KEYBOARD
    inp[1].i.ki.wVk = vk
    user32.SendInput(2, inp, ctypes.sizeof(INPUT))

def send_key_up(vk, sc):
    inp = (INPUT * 2)()
    inp[0].type = INPUT_KEYBOARD
    inp[0].i.ki.wScan = sc
    inp[0].i.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP
    inp[1].type = INPUT_KEYBOARD
    inp[1].i.ki.wVk = vk
    inp[1].i.ki.dwFlags = KEYEVENTF_KEYUP
    user32.SendInput(2, inp, ctypes.sizeof(INPUT))

# Save original foreground window
fg_orig = user32.GetForegroundWindow()
print(f"Original Foreground Window: {hex(fg_orig)}")

cur_tid = kernel32.GetCurrentThreadId()
poe_pid = wintypes.DWORD()
poe_tid = user32.GetWindowThreadProcessId(hwnd, ctypes.byref(poe_pid))
fg_tid = user32.GetWindowThreadProcessId(fg_orig, None) if fg_orig else 0

# Unlock Foreground
try:
    if hasattr(user32, "AllowSetForegroundWindow"):
        user32.AllowSetForegroundWindow(-1)
    SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001
    user32.SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0x0002)
except Exception:
    pass

attached_fg = False
attached_poe = False
if fg_tid and cur_tid != fg_tid:
    attached_fg = bool(user32.AttachThreadInput(cur_tid, fg_tid, True))
if poe_tid and cur_tid != poe_tid:
    attached_poe = bool(user32.AttachThreadInput(cur_tid, poe_tid, True))

print(f"Attached Threads: fg={attached_fg}, poe={attached_poe}")

# Alt-bypass to force foreground
user32.keybd_event(VK_MENU, 0, 0, 0)
user32.BringWindowToTop(hwnd)
user32.SetForegroundWindow(hwnd)
user32.SetActiveWindow(hwnd)
user32.SetFocus(hwnd)
user32.keybd_event(VK_MENU, 0, 2, 0)
time.sleep(0.08)

fg_now = user32.GetForegroundWindow()
print(f"Current Foreground Window: {hex(fg_now)}")

try:
    print("🚶 Bước 1: Giữ phím W (Bắc) 1.2s thoát Waypoint...")
    send_key_down(VK_W, SC_W)
    time.sleep(1.2)
    send_key_up(VK_W, SC_W)
    time.sleep(0.2)

    print("🚶 Bước 2: Giữ phím A (Tây) 1.2s áp sát Map Device...")
    send_key_down(VK_A, SC_A)
    time.sleep(1.2)
    send_key_up(VK_A, SC_A)
    time.sleep(0.2)

finally:
    # Immediately restore foreground window
    if fg_orig and fg_orig != hwnd:
        user32.keybd_event(VK_MENU, 0, 0, 0)
        user32.SetForegroundWindow(fg_orig)
        user32.keybd_event(VK_MENU, 0, 2, 0)
    if attached_fg:
        user32.AttachThreadInput(cur_tid, fg_tid, False)
    if attached_poe:
        user32.AttachThreadInput(cur_tid, poe_tid, False)
    print("✅ Đã khôi phục Foreground Window ban đầu!")

time.sleep(0.5)

# Verify new distance
img = capture_virtual_display()
img.save("captures/approach_result.png")
coord = AutonomousMappingCoordinator(1920, 1080, is_simulated=True)
md_pos = coord.find_map_device_screen_pos(img)
cx, cy = 960, 540
dist = math.hypot(md_pos[0] - cx, md_pos[1] - cy)
print(f"🎯 Kết quả: Tọa độ Map Device mới: {md_pos}, Cự ly tới tâm: {dist:.1f}px (Ngưỡng <= 180px)")
if dist <= 180.0:
    print("🎉 TUYỆT VỜI! ĐÃ TIẾP CẬN MAP DEVICE THÀNH CÔNG TRONG CỰ LY TƯƠNG TÁC!")
else:
    print(f"⚠️ Cần thêm bước điều chỉnh nếu cự ly chưa đạt ngưỡng.")
