"""
COM interface definitions for WebView2.

This module contains all the COM interface and GUID definitions required
for interacting with the WebView2 runtime via comtypes.

These interfaces correspond to the WebView2 Win32 API:
https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/

Note: Only the subset of methods actually used by this SDK are defined.
"""

import ctypes
from ctypes import wintypes

from comtypes import COMMETHOD, GUID, HRESULT, IUnknown

# =============================================================================
# Interface Identifiers (IIDs)
# =============================================================================
# These GUIDs are from the official WebView2 SDK headers.
# See: https://github.com/AzureAD/microsoft-authentication-library-for-cpp/blob/main/include/webview2.h

IID_ICoreWebView2Environment = GUID("{B96D6187-3505-40E9-A191-AE52151B2E3C}")
IID_ICoreWebView2Controller = GUID("{4D00C0D1-9435-4033-A696-03CF81F26D7A}")
IID_ICoreWebView2 = GUID("{76ECEACB-0462-4294-87D7-5CD0F86F3CC6}")
IID_ICoreWebView2Settings = GUID("{E562E4F0-D7FA-43AC-8D71-C05150499F00}")
IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = GUID(
    "{4E8A3389-C9D8-4BD2-B6B5-124FEE6CC14D}"
)
IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler = GUID(
    "{6C4819F3-C9B7-4260-8127-C9F5BDE7F68C}"
)
IID_ICoreWebView2WebMessageReceivedEventHandler = GUID(
    "{57213F19-00E6-49FA-8E07-898EA01ECBD2}"
)
IID_ICoreWebView2WebMessageReceivedEventArgs = GUID(
    "{0F99A40C-E962-4207-9E92-E3D542EFF849}"
)
IID_ICoreWebView2ProcessFailedEventHandler = GUID(
    "{8155A9F4-1330-4D50-9146-903543DD638D}"
)
# Note: ProcessFailedEventArgs has a different GUID than the handler
IID_ICoreWebView2ProcessFailedEventArgs = GUID(
    "{8A4C1C7F-F4A4-4B8E-9D9B-3E8E3E8D1F2A}"
)


# =============================================================================
# Forward declarations for COM interfaces
# =============================================================================
# Note: Methods are populated below after all interfaces are declared
# to handle circular references in the COM vtable definitions.


class ICoreWebView2Environment(IUnknown):
    """
    WebView2 environment COM interface.

    The environment represents the WebView2 runtime and is used to create
    controllers (which in turn create the actual webview instances).
    Each environment uses a specific browser version and user data folder.

    See: https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2environment
    """

    _iid_ = IID_ICoreWebView2Environment
    _methods_ = []  # Populated below after forward declarations


class ICoreWebView2Controller(IUnknown):
    """
    WebView2 controller COM interface.

    The controller manages the WebView2 control's parent window relationship,
    visibility, bounds, and focus. Each controller owns a single CoreWebView2.

    See: https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2controller
    """

    _iid_ = IID_ICoreWebView2Controller
    _methods_ = []  # Populated below after forward declarations


class ICoreWebView2(IUnknown):
    """
    Core WebView2 COM interface.

    This is the main interface for interacting with the web content.
    It provides methods for navigation, script execution, and event handling.

    See: https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2
    """

    _iid_ = IID_ICoreWebView2
    _methods_ = []  # Populated below after forward declarations


class ICoreWebView2Settings(IUnknown):
    """WebView2 settings interface for configuring browser behavior."""

    _iid_ = IID_ICoreWebView2Settings
    _methods_ = [
        # 1. get_IsScriptEnabled
        COMMETHOD(
            [],
            HRESULT,
            "get_IsScriptEnabled",
            (["out"], ctypes.POINTER(wintypes.BOOL), "isScriptEnabled"),
        ),
        # 2. put_IsScriptEnabled
        COMMETHOD(
            [],
            HRESULT,
            "put_IsScriptEnabled",
            (["in"], wintypes.BOOL, "isScriptEnabled"),
        ),
        # 3. get_IsWebMessageEnabled
        COMMETHOD(
            [],
            HRESULT,
            "get_IsWebMessageEnabled",
            (["out"], ctypes.POINTER(wintypes.BOOL), "isWebMessageEnabled"),
        ),
        # 4. put_IsWebMessageEnabled
        COMMETHOD(
            [],
            HRESULT,
            "put_IsWebMessageEnabled",
            (["in"], wintypes.BOOL, "isWebMessageEnabled"),
        ),
        # 5. get_AreDefaultScriptDialogsEnabled
        COMMETHOD(
            [],
            HRESULT,
            "get_AreDefaultScriptDialogsEnabled",
            (["out"], ctypes.POINTER(wintypes.BOOL), "areDefaultScriptDialogsEnabled"),
        ),
        # 6. put_AreDefaultScriptDialogsEnabled
        COMMETHOD(
            [],
            HRESULT,
            "put_AreDefaultScriptDialogsEnabled",
            (["in"], wintypes.BOOL, "areDefaultScriptDialogsEnabled"),
        ),
        # 7. get_IsStatusBarEnabled
        COMMETHOD(
            [],
            HRESULT,
            "get_IsStatusBarEnabled",
            (["out"], ctypes.POINTER(wintypes.BOOL), "isStatusBarEnabled"),
        ),
        # 8. put_IsStatusBarEnabled
        COMMETHOD(
            [],
            HRESULT,
            "put_IsStatusBarEnabled",
            (["in"], wintypes.BOOL, "isStatusBarEnabled"),
        ),
        # 9. get_AreDevToolsEnabled
        COMMETHOD(
            [],
            HRESULT,
            "get_AreDevToolsEnabled",
            (["out"], ctypes.POINTER(wintypes.BOOL), "areDevToolsEnabled"),
        ),
        # 10. put_AreDevToolsEnabled
        COMMETHOD(
            [],
            HRESULT,
            "put_AreDevToolsEnabled",
            (["in"], wintypes.BOOL, "areDevToolsEnabled"),
        ),
        # 11. get_AreDefaultContextMenusEnabled
        COMMETHOD(
            [],
            HRESULT,
            "get_AreDefaultContextMenusEnabled",
            (["out"], ctypes.POINTER(wintypes.BOOL), "areDefaultContextMenusEnabled"),
        ),
        # 12. put_AreDefaultContextMenusEnabled
        COMMETHOD(
            [],
            HRESULT,
            "put_AreDefaultContextMenusEnabled",
            (["in"], wintypes.BOOL, "areDefaultContextMenusEnabled"),
        ),
    ]


class ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(IUnknown):
    """Handler for environment creation completion callback."""

    _iid_ = IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
    _methods_ = [
        COMMETHOD(
            [],
            HRESULT,
            "Invoke",
            (["in"], HRESULT, "errorCode"),
            (["in"], ctypes.POINTER(ICoreWebView2Environment), "createdEnvironment"),
        )
    ]


class ICoreWebView2CreateCoreWebView2ControllerCompletedHandler(IUnknown):
    """Handler for controller creation completion callback."""

    _iid_ = IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler
    _methods_ = [
        COMMETHOD(
            [],
            HRESULT,
            "Invoke",
            (["in"], HRESULT, "errorCode"),
            (["in"], ctypes.POINTER(ICoreWebView2Controller), "createdController"),
        )
    ]


class ICoreWebView2WebMessageReceivedEventArgs(IUnknown):
    """Event args for web message received events."""

    _iid_ = IID_ICoreWebView2WebMessageReceivedEventArgs
    _methods_ = [
        COMMETHOD(
            [],
            HRESULT,
            "get_Source",
            (["out"], ctypes.POINTER(wintypes.LPWSTR), "source"),
        ),
        COMMETHOD(
            [],
            HRESULT,
            "get_WebMessageAsJson",
            (["out"], ctypes.POINTER(wintypes.LPWSTR), "webMessageAsJson"),
        ),
        COMMETHOD(
            [],
            HRESULT,
            "TryGetWebMessageAsString",
            (["out"], ctypes.POINTER(wintypes.LPWSTR), "webMessageAsString"),
        ),
    ]


class ICoreWebView2WebMessageReceivedEventHandler(IUnknown):
    """Handler for web message received events."""

    _iid_ = IID_ICoreWebView2WebMessageReceivedEventHandler
    _methods_ = [
        COMMETHOD(
            [],
            HRESULT,
            "Invoke",
            (["in"], ctypes.POINTER(IUnknown), "sender"),
            (["in"], ctypes.POINTER(ICoreWebView2WebMessageReceivedEventArgs), "args"),
        )
    ]


class ICoreWebView2ProcessFailedEventHandler(IUnknown):
    """Handler for process failure events."""

    _iid_ = IID_ICoreWebView2ProcessFailedEventHandler
    _methods_ = [
        COMMETHOD(
            [],
            HRESULT,
            "Invoke",
            (["in"], ctypes.POINTER(IUnknown), "sender"),
            (["in"], ctypes.POINTER(IUnknown), "args"),
        )
    ]


# Populate ICoreWebView2Environment methods
ICoreWebView2Environment._methods_ = [
    COMMETHOD(
        [],
        HRESULT,
        "CreateCoreWebView2Controller",
        (["in"], wintypes.HWND, "ParentWindow"),
        (
            ["in"],
            ctypes.POINTER(ICoreWebView2CreateCoreWebView2ControllerCompletedHandler),
            "handler",
        ),
    ),
    # Other methods omitted for brevity
]

# Populate ICoreWebView2Controller methods
ICoreWebView2Controller._methods_ = [
    COMMETHOD(
        [],
        HRESULT,
        "get_IsVisible",
        (["out"], ctypes.POINTER(wintypes.BOOL), "isVisible"),
    ),
    COMMETHOD([], HRESULT, "put_IsVisible", (["in"], wintypes.BOOL, "isVisible")),
    COMMETHOD(
        [], HRESULT, "get_Bounds", (["out"], ctypes.POINTER(wintypes.RECT), "bounds")
    ),
    COMMETHOD([], HRESULT, "put_Bounds", (["in"], wintypes.RECT, "bounds")),
    COMMETHOD(
        [],
        HRESULT,
        "get_ZoomFactor",
        (["out"], ctypes.POINTER(ctypes.c_double), "zoomFactor"),
    ),
    COMMETHOD([], HRESULT, "put_ZoomFactor", (["in"], ctypes.c_double, "zoomFactor")),
    COMMETHOD(
        [],
        HRESULT,
        "add_ZoomFactorChanged",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_ZoomFactorChanged", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "SetBoundsAndZoomFactor",
        (["in"], wintypes.RECT, "bounds"),
        (["in"], ctypes.c_double, "zoomFactor"),
    ),
    COMMETHOD([], HRESULT, "MoveFocus", (["in"], ctypes.c_int, "reason")),
    COMMETHOD(
        [],
        HRESULT,
        "add_MoveFocusRequested",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_MoveFocusRequested", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_GotFocus",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD([], HRESULT, "remove_GotFocus", (["in"], ctypes.c_longlong, "token")),
    COMMETHOD(
        [],
        HRESULT,
        "add_LostFocus",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD([], HRESULT, "remove_LostFocus", (["in"], ctypes.c_longlong, "token")),
    COMMETHOD(
        [],
        HRESULT,
        "add_AcceleratorKeyPressed",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "remove_AcceleratorKeyPressed",
        (["in"], ctypes.c_longlong, "token"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "get_ParentWindow",
        (["out"], ctypes.POINTER(wintypes.HWND), "parentWindow"),
    ),
    COMMETHOD([], HRESULT, "put_ParentWindow", (["in"], wintypes.HWND, "parentWindow")),
    COMMETHOD([], HRESULT, "NotifyParentWindowPositionChanged"),
    COMMETHOD([], HRESULT, "Close"),
    COMMETHOD(
        [],
        HRESULT,
        "get_CoreWebView2",
        (["out"], ctypes.POINTER(ctypes.POINTER(IUnknown)), "coreWebView2"),
    ),
]

# Populate ICoreWebView2 methods
ICoreWebView2._methods_ = [
    COMMETHOD(
        [],
        HRESULT,
        "get_Settings",
        (
            ["out"],
            ctypes.POINTER(ICoreWebView2Settings),
            "settings",
            ctypes.POINTER(ICoreWebView2Settings)(),
        ),
    ),
    COMMETHOD(
        [], HRESULT, "get_Source", (["out"], ctypes.POINTER(wintypes.LPWSTR), "uri")
    ),
    COMMETHOD([], HRESULT, "Navigate", (["in"], wintypes.LPWSTR, "uri")),
    COMMETHOD(
        [], HRESULT, "NavigateToString", (["in"], wintypes.LPWSTR, "htmlContent")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_NavigationStarting",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_NavigationStarting", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_ContentLoading",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_ContentLoading", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_SourceChanged",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_SourceChanged", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_HistoryChanged",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_HistoryChanged", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_NavigationCompleted",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_NavigationCompleted", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_FrameNavigationStarting",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "remove_FrameNavigationStarting",
        (["in"], ctypes.c_longlong, "token"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_FrameNavigationCompleted",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "remove_FrameNavigationCompleted",
        (["in"], ctypes.c_longlong, "token"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_ScriptDialogOpening",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_ScriptDialogOpening", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_PermissionRequested",
        (["in"], ctypes.POINTER(IUnknown), "eventHandler"),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_PermissionRequested", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_ProcessFailed",
        (
            ["in"],
            ctypes.POINTER(ICoreWebView2ProcessFailedEventHandler),
            "eventHandler",
        ),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_ProcessFailed", (["in"], ctypes.c_longlong, "token")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "AddScriptToExecuteOnDocumentCreated",
        (["in"], wintypes.LPWSTR, "javaScript"),
        (["in"], ctypes.POINTER(IUnknown), "handler"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "RemoveScriptToExecuteOnDocumentCreated",
        (["in"], ctypes.c_longlong, "id"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "ExecuteScript",
        (["in"], wintypes.LPWSTR, "javaScript"),
        (["in"], ctypes.POINTER(IUnknown), "handler"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "CapturePreview",
        (["in"], ctypes.c_int, "capturePreviewImageFormat"),
        (["in"], ctypes.POINTER(IUnknown), "stream"),
        (["in"], ctypes.POINTER(IUnknown), "handler"),
    ),
    COMMETHOD([], HRESULT, "Reload"),
    COMMETHOD(
        [],
        HRESULT,
        "PostWebMessageAsJson",
        (["in"], wintypes.LPWSTR, "webMessageAsJson"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "PostWebMessageAsString",
        (["in"], wintypes.LPWSTR, "webMessageAsString"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "add_WebMessageReceived",
        (
            ["in"],
            ctypes.POINTER(ICoreWebView2WebMessageReceivedEventHandler),
            "handler",
        ),
        (["out"], ctypes.POINTER(ctypes.c_longlong), "token"),
    ),
    COMMETHOD(
        [], HRESULT, "remove_WebMessageReceived", (["in"], ctypes.c_longlong, "token")
    ),
]
