import time
import ctypes
from ctypes import wintypes
import sys
import os
from pathlib import Path
from PIL import Image, ImageChops, ImageStat

sys.path.insert(0, str(Path(".").resolve()))
from src.assistant_tool.client_launcher import Poe2ClientLauncher
from src.common.win32_window import find_poe2_window, attach_to_window_desktop, ensure_window_focus, is_poe2_window_focused, get_client_rect
from src.common.win32_input import (
    INPUT, INPUT_KEYBOARD, KEYEVENTF_SCANCODE, KEYEVENTF_KEYUP,
    VK_W, SC_W, VK_A, SC_A, VK_S, SC_S, VK_D, SC_D
)
from src.common.screen_capture import capture_window_bitblt
import src.common.vision_ocr as vision_ocr
import scripts.reconnect_and_enter_hideout as reconnect_module

def ensure_in_hideout():
    hwnd = find_poe2_window()
    if not hwnd or not Poe2ClientLauncher.is_client_window_ready():
        print("[Probe] Client chưa chạy, đang khởi chạy qua Poe2ClientLauncher...", flush=True)
        Poe2ClientLauncher.launch_client(wait_timeout_sec=60)
        hwnd = find_poe2_window()
        time.sleep(2.0)
    
    attach_to_window_desktop(hwnd)
    ensure_window_focus(hwnd)
    
    # Kiểm tra xem đang ở Hideout chưa
    cap = capture_window_bitblt(hwnd, client_only=True)
    res = vision_ocr.safe_recognize_pil_sync(cap)
    txt = " ".join(l.get("text", "") for l in res.get("lines", [])).upper()
    if not ("MAP DEVICE" in txt or "WAYPOINT" in txt or "SHORELINE" in txt):
        print("[Probe] Chưa ở Hideout, kích hoạt reconnect...", flush=True)
        rc = reconnect_module.main(hwnd=hwnd)
        print(f"[Probe] Reconnect result: {rc}", flush=True)
        time.sleep(5.0)
    else:
        print("[Probe] Đã ở Hideout sẵn sàng!", flush=True)
    return hwnd

def extract_pos(pil_img):
    res = vision_ocr.safe_recognize_pil_sync(pil_img)
    pos = {}
    for l in res.get("lines", []):
        for k in ["MAP DEVICE", "WAYPOINT", "ANGE", "WELL"]:
            if k in l.get("text", "").upper():
                words = l.get("words", [])
                if words:
                    r = words[0].get("bounding_rect", {})
                    pos[k] = (round(r.get("x", 0), 1), round(r.get("y", 0), 1))
    return pos

def send_single_press_hold(scancode: int, hold_sec: float, hwnd: int):
    """Kỹ thuật Người Chơi Thật: Gửi Make Code (KeyDown) 1 LẦN DUY NHẤT, giữ hold_sec, rồi gửi Break Code (KeyUp) 1 LẦN DUY NHẤT."""
    attach_to_window_desktop(hwnd)
    ensure_window_focus(hwnd)
    time.sleep(0.1)
    
    user32 = ctypes.windll.user32
    inp_down = INPUT()
    inp_down.type = INPUT_KEYBOARD
    inp_down.i.ki.wVk = 0
    inp_down.i.ki.wScan = scancode
    inp_down.i.ki.dwFlags = KEYEVENTF_SCANCODE
    inp_down.i.ki.time = 0
    
    inp_up = INPUT()
    inp_up.type = INPUT_KEYBOARD
    inp_up.i.ki.wVk = 0
    inp_up.i.ki.wScan = scancode
    inp_up.i.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP
    inp_up.i.ki.time = 0
    
    # 1. KeyDown
    ret_down = user32.SendInput(1, ctypes.byref(inp_down), ctypes.sizeof(INPUT))
    user32.keybd_event(0, scancode, KEYEVENTF_SCANCODE, 0)
    print(f"  [KeyDown sc={hex(scancode)}] SendInput ret={ret_down}")
    
    # 2. Hold
    time.sleep(hold_sec)
    
    # 3. KeyUp
    ret_up = user32.SendInput(1, ctypes.byref(inp_up), ctypes.sizeof(INPUT))
    user32.keybd_event(0, scancode, KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, 0)
    print(f"  [KeyUp sc={hex(scancode)}] SendInput ret={ret_up}")
    time.sleep(0.3)

def main():
    hwnd = ensure_in_hideout()
    ensure_window_focus(hwnd)
    time.sleep(1.0)
    
    img0 = capture_window_bitblt(hwnd, client_only=True)
    img0.save("captures/probe_tech_initial.png")
    pos0 = extract_pos(img0)
    print("Initial Positions:", pos0, flush=True)
    
    # THỰC NGHIỆM 1: Single KeyDown -> Hold 2.0s -> KeyUp (Phím W - bước lên phía Bắc)
    print("\n--- THỰC NGHIỆM 1: Single Press & Hold W (2.0s) ---", flush=True)
    send_single_press_hold(SC_W, 2.0, hwnd)
    
    img1 = capture_window_bitblt(hwnd, client_only=True)
    img1.save("captures/probe_tech_after_single_w.png")
    pos1 = extract_pos(img1)
    diff1 = ImageStat.Stat(ImageChops.difference(img0, img1)).mean
    print("After Single W:", pos1, flush=True)
    print("Pixel Diff Mean:", diff1, flush=True)
    
    # Kiểm tra xem nhãn có dịch chuyển không
    moved_w = False
    if pos0.get("MAP DEVICE") and pos1.get("MAP DEVICE"):
        dx = abs(pos1["MAP DEVICE"][0] - pos0["MAP DEVICE"][0])
        dy = abs(pos1["MAP DEVICE"][1] - pos0["MAP DEVICE"][1])
        print(f"Delta Map Device: dx={dx}, dy={dy}", flush=True)
        if dx > 10 or dy > 10:
            moved_w = True
            print(">>> KẾT QUẢ: PHÍM W ĐÃ DI CHUYỂN THÀNH CÔNG NHÂN VẬT! <<<", flush=True)
    
    # THỰC NGHIỆM 2: Single Press & Hold A (2.0s) (rẽ sang phía Tây)
    print("\n--- THỰC NGHIỆM 2: Single Press & Hold A (2.0s) ---", flush=True)
    send_single_press_hold(SC_A, 2.0, hwnd)
    
    img2 = capture_window_bitblt(hwnd, client_only=True)
    img2.save("captures/probe_tech_after_single_a.png")
    pos2 = extract_pos(img2)
    diff2 = ImageStat.Stat(ImageChops.difference(img1, img2)).mean
    print("After Single A:", pos2, flush=True)
    print("Pixel Diff Mean:", diff2, flush=True)
    
    if pos1.get("MAP DEVICE") and pos2.get("MAP DEVICE"):
        dx = abs(pos2["MAP DEVICE"][0] - pos1["MAP DEVICE"][0])
        dy = abs(pos2["MAP DEVICE"][1] - pos1["MAP DEVICE"][1])
        print(f"Delta Map Device: dx={dx}, dy={dy}", flush=True)
        if dx > 10 or dy > 10:
            print(">>> KẾT QUẢ: PHÍM A ĐÃ DI CHUYỂN THÀNH CÔNG NHÂN VẬT! <<<", flush=True)

if __name__ == "__main__":
    main()
