# -*- coding: utf-8 -*-
import os

target_path = r"C:\OptimusProjects\Optimus Developer\src\core\effector_runtime.py"

with open(target_path, "r", encoding="utf-8") as f:
    content = f.read()

# Replace argtypes section to include AllowSetForegroundWindow & SwitchToThisWindow
old_argtypes = """        user32.AttachThreadInput.argtypes = [wintypes.DWORD, wintypes.DWORD, wintypes.BOOL]
        user32.AttachThreadInput.restype = wintypes.BOOL
        user32.GetAncestor.argtypes = [wintypes.HWND, ctypes.c_uint]
        user32.GetAncestor.restype = wintypes.HWND
        kernel32.GetCurrentThreadId.argtypes = []
        kernel32.GetCurrentThreadId.restype = wintypes.DWORD"""

new_argtypes = """        user32.AttachThreadInput.argtypes = [wintypes.DWORD, wintypes.DWORD, wintypes.BOOL]
        user32.AttachThreadInput.restype = wintypes.BOOL
        user32.GetAncestor.argtypes = [wintypes.HWND, ctypes.c_uint]
        user32.GetAncestor.restype = wintypes.HWND
        try:
            user32.AllowSetForegroundWindow.argtypes = [wintypes.DWORD]
            user32.AllowSetForegroundWindow.restype = wintypes.BOOL
            user32.SwitchToThisWindow.argtypes = [wintypes.HWND, wintypes.BOOL]
            user32.SwitchToThisWindow.restype = None
        except Exception:
            pass
        kernel32.GetCurrentThreadId.argtypes = []
        kernel32.GetCurrentThreadId.restype = wintypes.DWORD"""

if old_argtypes in content:
    content = content.replace(old_argtypes, new_argtypes)
    print("Argtypes updated.")
else:
    print("Argtypes block not found or already updated.")

# Replace helper functions: is_target_foreground and activate_foreground
old_helpers = """        def is_target_foreground(target_h: int) -> bool:
            if not target_h:
                return False
            fg = user32.GetForegroundWindow() or 0
            if fg == target_h:
                return True
            if fg and user32.GetAncestor(fg, 2) == target_h:
                return True
            return False

        def activate_foreground(target_h: int, max_attempts: int = 5, retry_interval: float = 0.15) -> bool:
            if not target_h or not user32.IsWindow(target_h) or not user32.IsWindowVisible(target_h):
                return False
            if is_target_foreground(target_h):
                return True

            cur_thread = kernel32.GetCurrentThreadId()
            for _ in range(max_attempts):
                if is_target_foreground(target_h):
                    return True

                fg_curr = user32.GetForegroundWindow() or 0
                fg_thread = user32.GetWindowThreadProcessId(fg_curr, None) if fg_curr else 0
                target_thread = user32.GetWindowThreadProcessId(target_h, None)

                attached_fg = False
                attached_target = False
                if fg_thread and fg_thread != cur_thread:
                    attached_fg = bool(user32.AttachThreadInput(cur_thread, fg_thread, True))
                if target_thread and target_thread != cur_thread:
                    attached_target = bool(user32.AttachThreadInput(cur_thread, target_thread, True))

                try:
                    user32.keybd_event(0x12, 0, 0, 0)
                    user32.ShowWindow(target_h, 9)
                    user32.BringWindowToTop(target_h)
                    user32.SetForegroundWindow(target_h)
                    user32.SetFocus(target_h)
                    user32.keybd_event(0x12, 0, 2, 0)
                finally:
                    if attached_fg:
                        user32.AttachThreadInput(cur_thread, fg_thread, False)
                    if attached_target:
                        user32.AttachThreadInput(cur_thread, target_thread, False)

                time.sleep(retry_interval)
                if is_target_foreground(target_h):
                    return True

            return is_target_foreground(target_h)"""

new_helpers = """        # Ensure current thread is attached to user's interactive desktop
        try:
            hdesk_def = user32.OpenDesktopW("Default", 0, False, 0x01FF)
            if hdesk_def:
                user32.SetThreadDesktop(hdesk_def)
        except Exception:
            pass

        def is_target_foreground(target_h: int) -> bool:
            if not target_h:
                return False
            fg = user32.GetForegroundWindow() or 0
            if fg == target_h:
                return True
            if fg and user32.GetAncestor(fg, 2) == target_h:
                return True
            if fg and user32.GetAncestor(target_h, 2) == fg:
                return True
            # Match process id
            pid_fg = wintypes.DWORD()
            pid_target = wintypes.DWORD()
            user32.GetWindowThreadProcessId(fg, ctypes.byref(pid_fg))
            user32.GetWindowThreadProcessId(target_h, ctypes.byref(pid_target))
            if pid_fg.value and pid_target.value and pid_fg.value == pid_target.value:
                return True
            return False

        def activate_foreground(target_h: int, max_attempts: int = 6, retry_interval: float = 0.15) -> bool:
            if not target_h or not user32.IsWindow(target_h) or not user32.IsWindowVisible(target_h):
                return False
            if is_target_foreground(target_h):
                return True

            try:
                user32.AllowSetForegroundWindow(0xFFFFFFFF)
            except Exception:
                pass

            cur_thread = kernel32.GetCurrentThreadId()
            for _ in range(max_attempts):
                if is_target_foreground(target_h):
                    return True

                fg_curr = user32.GetForegroundWindow() or 0
                fg_thread = user32.GetWindowThreadProcessId(fg_curr, None) if fg_curr else 0
                target_thread = user32.GetWindowThreadProcessId(target_h, None)

                attached_fg = False
                attached_target = False
                if fg_thread and fg_thread != cur_thread:
                    attached_fg = bool(user32.AttachThreadInput(cur_thread, fg_thread, True))
                if target_thread and target_thread != cur_thread:
                    attached_target = bool(user32.AttachThreadInput(cur_thread, target_thread, True))

                try:
                    user32.keybd_event(0x12, 0, 0, 0)
                    user32.ShowWindow(target_h, 9)
                    user32.BringWindowToTop(target_h)
                    user32.SetForegroundWindow(target_h)
                    user32.SetFocus(target_h)
                    try:
                        user32.SwitchToThisWindow(target_h, True)
                    except Exception:
                        pass
                    user32.keybd_event(0x12, 0, 2, 0)
                finally:
                    if attached_fg:
                        user32.AttachThreadInput(cur_thread, fg_thread, False)
                    if attached_target:
                        user32.AttachThreadInput(cur_thread, target_thread, False)

                time.sleep(retry_interval)
                if is_target_foreground(target_h):
                    return True

            return is_target_foreground(target_h)"""

if old_helpers in content:
    content = content.replace(old_helpers, new_helpers)
    print("Helpers updated.")
else:
    print("Helpers block not found or already updated.")

# In TYPE_TEXT, ensure verified=True / False in evidence and is_target_foreground in is_final_target
old_final_target = """                is_final_target = bool(
                    is_fg_ok
                    and expected_hwnd > 0
                    and user32.IsWindow(expected_hwnd)
                    and user32.IsWindowVisible(expected_hwnd)
                    and (fg_hwnd_current == expected_hwnd or (fg_hwnd_current and user32.GetAncestor(fg_hwnd_current, 2) == expected_hwnd))
                )"""

new_final_target = """                is_final_target = bool(
                    is_fg_ok
                    and expected_hwnd > 0
                    and user32.IsWindow(expected_hwnd)
                    and user32.IsWindowVisible(expected_hwnd)
                    and is_target_foreground(expected_hwnd)
                )"""

if old_final_target in content:
    content = content.replace(old_final_target, new_final_target)
    print("is_final_target updated.")

old_fail_ev = """"target_validated": False,
                        "chars_count": 0,"""

new_fail_ev = """"target_validated": False,
                        "verified": False,
                        "chars_count": 0,"""

if old_fail_ev in content:
    content = content.replace(old_fail_ev, new_fail_ev)
    print("Fail evidence verified added.")

old_post_alive = """                post_alive = bool(
                    expected_hwnd > 0
                    and user32.IsWindow(expected_hwnd)
                    and user32.IsWindowVisible(expected_hwnd)
                    and (fg_hwnd_after == expected_hwnd or (fg_hwnd_after and user32.GetAncestor(fg_hwnd_after, 2) == expected_hwnd))
                )"""

new_post_alive = """                post_alive = bool(
                    expected_hwnd > 0
                    and user32.IsWindow(expected_hwnd)
                    and user32.IsWindowVisible(expected_hwnd)
                    and is_target_foreground(expected_hwnd)
                )"""

if old_post_alive in content:
    content = content.replace(old_post_alive, new_post_alive)
    print("post_alive updated.")

old_succ_ev = """"target_validated": post_alive,
                    "chars_count": len(text),"""

new_succ_ev = """"target_validated": post_alive,
                    "verified": post_alive,
                    "chars_count": len(text),"""

if old_succ_ev in content:
    content = content.replace(old_succ_ev, new_succ_ev)
    print("Success evidence verified added.")

# In WINDOW_FOCUS, make sure is_fg uses is_target_foreground
old_wf = """                    is_fg = bool(fg_hwnd == matched_hwnd or (fg_hwnd and user32.GetAncestor(fg_hwnd, 2) == matched_hwnd))"""
new_wf = """                    is_fg = is_target_foreground(matched_hwnd)"""

if old_wf in content:
    content = content.replace(old_wf, new_wf)
    print("WINDOW_FOCUS is_fg updated.")

with open(target_path, "w", encoding="utf-8") as f:
    f.write(content)

print("Patch complete.")
