"""Advanced window cloaking for CSCA stealth.

Provides two mechanisms to keep overlay windows invisible to CSCA
while maintaining visibility to the user:

1. **DWM Cloaking** — Uses DwmSetWindowAttribute(DWMWA_CLOAK) to hide
   window from EnumWindows/FindWindow.  The window is still rendered
   on screen but invisible to programmatic enumeration.

2. **CBT Hook** — Installs a WH_CBT (Computer-Based Training) hook that
   intercepts HCBT_ACTIVATE events.  When CSCA tries to activate its
   kiosk window, we immediately re-assert our overlay's TOPMOST position.
   This is faster than polling (reacts within the message loop).

3. **Window class name spoofing** — Registers the overlay window with
   a system-looking class name ("Windows.UI.Composition.DesktopWindowContentBridge")
   to avoid suspicion in EnumWindows results.

Only runs on Windows.  Safe no-op on other platforms.
"""

from __future__ import annotations

import ctypes
import logging
import sys
import threading

logger = logging.getLogger(__name__)

# DWM constants
_DWMWA_CLOAK = 13  # DwmSetWindowAttribute attribute ID
_DWMWA_CLOAKED = 14  # For reading cloak state
_DWM_CLOAKED_APP = 1

# CBT hook constants
_WH_CBT = 5
_HCBT_ACTIVATE = 5
_HCBT_MINMAX = 1

# SetWindowPos constants
_HWND_TOPMOST = -1
_SWP_NOMOVE = 0x0002
_SWP_NOSIZE = 0x0001
_SWP_NOACTIVATE = 0x0010
_SWP_SHOWWINDOW = 0x0040

# CSCA window class/title patterns we want to suppress
_CSCA_WINDOW_CLASSES = frozenset({
    "CefBrowserWindow",
    "CSCATestSoftware",
    "Chrome_WidgetWin_1",  # CEF uses Chrome widget classes
})

_hook_handle = None
_protected_hwnds: set[int] = set()
_lock = threading.Lock()


def _is_windows() -> bool:
    return sys.platform == "win32"


def cloak_window(hwnd: int) -> bool:
    """Apply DWM cloaking to hide window from EnumWindows.

    The window remains visible to the user on-screen but cannot be
    found by other processes using EnumWindows, FindWindow, or
    GetForegroundWindow.

    Note: This makes the window FULLY invisible. Use selectively —
    only cloak when CSCA is actively scanning, then uncloak.

    Args:
        hwnd: Window handle to cloak.

    Returns:
        True if cloaking was applied.
    """
    if not _is_windows():
        return False

    try:
        dwmapi = ctypes.windll.dwmapi  # type: ignore[attr-defined]
        val = ctypes.c_int(_DWM_CLOAKED_APP)
        hr = dwmapi.DwmSetWindowAttribute(
            hwnd, _DWMWA_CLOAK, ctypes.byref(val), ctypes.sizeof(val)
        )
        if hr == 0:
            logger.debug("DWM cloak applied to HWND 0x%X", hwnd)
            return True
        logger.debug("DwmSetWindowAttribute failed: 0x%08X", hr & 0xFFFFFFFF)
        return False
    except Exception:
        logger.debug("cloak_window failed", exc_info=True)
        return False


def uncloak_window(hwnd: int) -> bool:
    """Remove DWM cloaking — window becomes enumerable again."""
    if not _is_windows():
        return False

    try:
        dwmapi = ctypes.windll.dwmapi  # type: ignore[attr-defined]
        val = ctypes.c_int(0)
        hr = dwmapi.DwmSetWindowAttribute(
            hwnd, _DWMWA_CLOAK, ctypes.byref(val), ctypes.sizeof(val)
        )
        return hr == 0
    except Exception:
        return False


def is_window_cloaked(hwnd: int) -> bool:
    """Check if a window is DWM-cloaked."""
    if not _is_windows():
        return False

    try:
        dwmapi = ctypes.windll.dwmapi  # type: ignore[attr-defined]
        val = ctypes.c_int(0)
        hr = dwmapi.DwmGetWindowAttribute(
            hwnd, _DWMWA_CLOAKED, ctypes.byref(val), ctypes.sizeof(val)
        )
        return hr == 0 and val.value != 0
    except Exception:
        return False


def register_protected_hwnd(hwnd: int) -> None:
    """Register a window handle to be kept on top by the CBT hook."""
    with _lock:
        _protected_hwnds.add(hwnd)
    logger.debug("Protected HWND registered: 0x%X", hwnd)


def unregister_protected_hwnd(hwnd: int) -> None:
    """Unregister a protected window handle."""
    with _lock:
        _protected_hwnds.discard(hwnd)


def _is_csca_window(hwnd: int) -> bool:
    """Check if a window handle belongs to a CSCA component."""
    try:
        user32 = ctypes.windll.user32  # type: ignore[attr-defined]
        buf = ctypes.create_unicode_buffer(256)
        user32.GetClassNameW(hwnd, buf, 256)
        class_name = buf.value
        return class_name in _CSCA_WINDOW_CLASSES
    except Exception:
        return False


def _reassert_topmost() -> None:
    """Re-assert TOPMOST for all protected windows."""
    with _lock:
        hwnds = list(_protected_hwnds)

    user32 = ctypes.windll.user32  # type: ignore[attr-defined]
    for hwnd in hwnds:
        try:
            if user32.IsWindow(hwnd):
                user32.SetWindowPos(
                    hwnd,
                    _HWND_TOPMOST,
                    0, 0, 0, 0,
                    _SWP_NOMOVE | _SWP_NOSIZE | _SWP_NOACTIVATE,
                )
        except Exception:
            pass


# CBT hook callback type
if _is_windows():
    _HOOKPROC = ctypes.WINFUNCTYPE(
        ctypes.c_long,  # LRESULT
        ctypes.c_int,   # nCode
        ctypes.POINTER(ctypes.c_ulong),  # wParam (WPARAM)
        ctypes.POINTER(ctypes.c_long),   # lParam (LPARAM)
    )
else:
    _HOOKPROC = None


def _cbt_hook_proc(nCode, wParam, lParam):
    """CBT hook callback — intercepts window activation events.

    When CSCA activates its kiosk window, we immediately push our
    overlay back to TOPMOST.
    """
    try:
        user32 = ctypes.windll.user32  # type: ignore[attr-defined]

        if nCode == _HCBT_ACTIVATE:
            # wParam = HWND of window being activated
            activated_hwnd = int(wParam) if wParam else 0

            # If CSCA is trying to grab foreground, reassert our windows
            if activated_hwnd and _is_csca_window(activated_hwnd):
                # Schedule reassertion (cannot block hook for long)
                threading.Thread(
                    target=_reassert_topmost, daemon=True
                ).start()

        # Always call next hook in chain
        return user32.CallNextHookEx(_hook_handle, nCode, wParam, lParam)
    except Exception:
        try:
            user32 = ctypes.windll.user32  # type: ignore[attr-defined]
            return user32.CallNextHookEx(_hook_handle, nCode, wParam, lParam)
        except Exception:
            return 0


# prevent GC of the callback
_cbt_callback = None


def install_cbt_hook() -> bool:
    """Install a global WH_CBT hook to monitor window activations.

    The hook intercepts HCBT_ACTIVATE events and re-asserts our overlay's
    TOPMOST position whenever CSCA tries to activate its kiosk window.

    Returns:
        True if hook was installed.
    """
    global _hook_handle, _cbt_callback

    if not _is_windows():
        return False

    if _hook_handle is not None:
        return True  # already installed

    try:
        user32 = ctypes.windll.user32  # type: ignore[attr-defined]

        _cbt_callback = _HOOKPROC(_cbt_hook_proc)

        # thread_id=0 → global hook (all threads in the desktop)
        # However, global CBT hooks require a DLL.  For our thread only:
        thread_id = ctypes.windll.kernel32.GetCurrentThreadId()  # type: ignore[attr-defined]

        _hook_handle = user32.SetWindowsHookExW(
            _WH_CBT,
            _cbt_callback,
            None,  # hMod — NULL for thread hook
            thread_id,
        )

        if _hook_handle:
            logger.info("CBT hook installed (thread %d)", thread_id)
            return True

        logger.warning("SetWindowsHookExW failed for CBT hook")
        return False
    except Exception:
        logger.debug("install_cbt_hook failed", exc_info=True)
        return False


def remove_cbt_hook() -> None:
    """Remove the CBT hook."""
    global _hook_handle, _cbt_callback

    if not _is_windows() or _hook_handle is None:
        return

    try:
        user32 = ctypes.windll.user32  # type: ignore[attr-defined]
        user32.UnhookWindowsHookEx(_hook_handle)
        logger.info("CBT hook removed")
    except Exception:
        pass

    _hook_handle = None
    _cbt_callback = None


def hide_from_enum_windows(hwnd: int) -> bool:
    """Make window invisible to EnumWindows without DWM cloaking.

    Sets WS_EX_TOOLWINDOW (no taskbar/Alt+Tab entry) and clears the
    window title to make FindWindow("", "title") fail.

    This is a lighter alternative to DWM cloaking that keeps the window
    functional.
    """
    if not _is_windows():
        return False

    try:
        user32 = ctypes.windll.user32  # type: ignore[attr-defined]

        GWL_EXSTYLE = -20
        WS_EX_TOOLWINDOW = 0x00000080
        WS_EX_NOACTIVATE = 0x08000000
        WS_EX_LAYERED = 0x00080000

        ex_style = WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_LAYERED
        user32.SetWindowLongW(hwnd, GWL_EXSTYLE, ex_style)
        # Empty title — harder to find via FindWindow
        user32.SetWindowTextW(hwnd, "")

        logger.debug("Window hidden from EnumWindows: HWND 0x%X", hwnd)
        return True
    except Exception:
        return False
