#!/usr/bin/env python

"""Tests for `bleak.backends.winrt.util` package."""

import sys

import pytest

if sys.platform != "win32":
    pytest.skip("skipping windows-only tests", allow_module_level=True)
    # HACK: work around pyright bug
    allow_sta: object

from ctypes import windll, wintypes  # type: ignore[attr-defined]

from bleak.backends.winrt.util import (
    allow_sta,
    assert_mta,
    check_hresult,
    uninitialize_sta,
)
from bleak.exc import BleakError

# https://learn.microsoft.com/en-us/windows/win32/api/objbase/ne-objbase-coinit
COINIT_MULTITHREADED = 0x0
COINIT_APARTMENTTHREADED = 0x2

# https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex
_CoInitializeEx = windll.ole32.CoInitializeEx
_CoInitializeEx.restype = wintypes.LONG
_CoInitializeEx.argtypes = [wintypes.LPVOID, wintypes.DWORD]
_CoInitializeEx.errcheck = check_hresult  # type: ignore[assignment]

# https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-couninitialize
_CoUninitialize = windll.ole32.CoUninitialize
_CoUninitialize.restype = None
_CoUninitialize.argtypes = []


@pytest.fixture(autouse=True)
def run_around_tests():
    # reset global state
    try:
        delattr(allow_sta, "_allowed")
    except AttributeError:
        pass

    yield


@pytest.mark.asyncio
async def test_assert_mta_no_init():
    """Test device_path_from_characteristic_path."""

    await assert_mta()


@pytest.mark.asyncio
async def test_assert_mta_init_mta():
    """Test device_path_from_characteristic_path."""

    _CoInitializeEx(None, COINIT_MULTITHREADED)

    try:
        await assert_mta()
        assert hasattr(allow_sta, "_allowed")
    finally:
        _CoUninitialize()


@pytest.mark.asyncio
async def test_assert_mta_init_sta():
    """Test device_path_from_characteristic_path."""

    _CoInitializeEx(None, COINIT_APARTMENTTHREADED)

    try:
        with pytest.raises(
            BleakError,
            match="Thread is configured for Windows GUI but callbacks are not working.",
        ):
            await assert_mta()
    finally:
        _CoUninitialize()


@pytest.mark.asyncio
async def test_uninitialize_sta():
    """Test device_path_from_characteristic_path."""

    _CoInitializeEx(None, COINIT_APARTMENTTHREADED)
    uninitialize_sta()

    await assert_mta()
