"""Process-wide single-instance guard for the desktop app."""
from __future__ import annotations

import atexit
import ctypes
import os
from ctypes import wintypes


ERROR_ALREADY_EXISTS = 183
ERROR_ACCESS_DENIED = 5
MB_ICONINFORMATION = 0x00000040
MB_OK = 0x00000000
MB_SETFOREGROUND = 0x00010000
MB_TOPMOST = 0x00040000

MUTEX_NAMES = (
    r"Global\INI_HOP_DONG_INI_SINGLE_INSTANCE_78C3B5C2_4D2F_4E38_9566_52E7C1E56F30",
    r"Local\INI_HOP_DONG_INI_SINGLE_INSTANCE_78C3B5C2_4D2F_4E38_9566_52E7C1E56F30",
)


class SingleInstanceLock:
    def __init__(self):
        self._handle = None
        self.name = ""

    def acquire(self) -> bool:
        if os.name != "nt":
            return True

        kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
        kernel32.CreateMutexW.argtypes = (wintypes.LPVOID, wintypes.BOOL, wintypes.LPCWSTR)
        kernel32.CreateMutexW.restype = wintypes.HANDLE
        kernel32.CloseHandle.argtypes = (wintypes.HANDLE,)
        kernel32.CloseHandle.restype = wintypes.BOOL

        for mutex_name in MUTEX_NAMES:
            ctypes.set_last_error(0)
            handle = kernel32.CreateMutexW(None, True, mutex_name)
            last_error = ctypes.get_last_error()

            if handle:
                if last_error == ERROR_ALREADY_EXISTS:
                    kernel32.CloseHandle(handle)
                    return False
                self._handle = handle
                self.name = mutex_name
                return True

            if last_error in (ERROR_ALREADY_EXISTS, ERROR_ACCESS_DENIED):
                return False

        # If Windows refuses to create the guard for an unexpected reason, let the
        # app open instead of blocking legitimate users.
        return True

    def release(self):
        if self._handle and os.name == "nt":
            try:
                ctypes.WinDLL("kernel32", use_last_error=True).CloseHandle(self._handle)
            except Exception:
                pass
        self._handle = None


def acquire_single_instance_lock() -> SingleInstanceLock | None:
    lock = SingleInstanceLock()
    if not lock.acquire():
        return None
    atexit.register(lock.release)
    return lock


def show_already_running_message():
    message = (
        "Phần mềm đang được mở trên máy tính này.\n\n"
        "Vui lòng dùng cửa sổ đang mở hoặc đóng phần mềm trước khi mở lại."
    )
    title = "Hợp Đồng INI"

    if os.name == "nt":
        ctypes.windll.user32.MessageBoxW(
            None,
            message,
            title,
            MB_OK | MB_ICONINFORMATION | MB_TOPMOST | MB_SETFOREGROUND,
        )
        return

    print(f"{title}: {message}")
