from __future__ import annotations

import os
from pathlib import Path
import uuid


FOLDERID_SAVED_GAMES = uuid.UUID("4c5c32ff-bb9d-43b0-b5b4-2d72e54eaaa4")


def _windows_saved_games_folder() -> Path | None:
    if os.name != "nt":
        return None

    try:
        import ctypes
        from ctypes import wintypes

        class Guid(ctypes.Structure):
            _fields_ = (
                ("Data1", ctypes.c_ulong),
                ("Data2", ctypes.c_ushort),
                ("Data3", ctypes.c_ushort),
                ("Data4", ctypes.c_ubyte * 8),
            )

        folder_id = Guid.from_buffer_copy(FOLDERID_SAVED_GAMES.bytes_le)
        raw_path = ctypes.c_void_p()
        shell32 = ctypes.WinDLL("shell32", use_last_error=True)
        ole32 = ctypes.WinDLL("ole32", use_last_error=True)
        shell32.SHGetKnownFolderPath.argtypes = (
            ctypes.POINTER(Guid),
            wintypes.DWORD,
            wintypes.HANDLE,
            ctypes.POINTER(ctypes.c_void_p),
        )
        shell32.SHGetKnownFolderPath.restype = ctypes.c_long
        ole32.CoTaskMemFree.argtypes = (ctypes.c_void_p,)
        ole32.CoTaskMemFree.restype = None
        result = shell32.SHGetKnownFolderPath(
            ctypes.byref(folder_id),
            0,
            None,
            ctypes.byref(raw_path),
        )
        try:
            if result != 0 or not raw_path.value:
                return None
            value = ctypes.wstring_at(raw_path.value).strip()
            return Path(value) if value else None
        finally:
            if raw_path.value:
                ole32.CoTaskMemFree(raw_path)
    except (AttributeError, OSError, TypeError, ValueError):
        return None


def _fallback_saved_games_folder() -> Path:
    return Path.home() / "Saved Games"


def saved_games_folder() -> Path:
    """Return the current user's Windows Saved Games known folder."""
    return _windows_saved_games_folder() or _fallback_saved_games_folder()


def ace_root(override: str | Path | None = None) -> Path:
    """Return an explicit ACE root or resolve it below Windows Saved Games."""
    if override is not None and str(override).strip():
        return Path(override).expanduser()
    return saved_games_folder() / "ACE"
