"""Utility functions for validating paths and modules."""

import importlib
import os
import platform
import sys
from pathlib import Path
from typing import TYPE_CHECKING, Literal

from rizomuvbridge_ultimate import constants

if TYPE_CHECKING:
    from rizomuvbridge_ultimate.preferences import RizomUVBridgePreferences


def get_file_as_string(data_dir: Path, file_format: Literal["OBJ", "FBX", "USD"]) -> str:
    """Resolve the correct file path and return it as a string.

    Args:
    ----
        data_dir: Path to the data directory.
        file_format: Format of the file.

    Returns:
    -------
        Path to the file.

    """
    mesh_path = {
        "OBJ": constants.OBJ,
        "FBX": constants.FBX,
        "USD": constants.USD,
    }

    file_path = data_dir / Path(mesh_path[file_format])
    return str(file_path)


def get_latest_rizom_location() -> str | None:
    """Windows only, Locate the latest version of RizomUV installed on the system.

    Returns
    -------
        str: Path to the RizomUV executable or an None if it could not be found

    """
    import winreg

    for major in range(9, 1, -1):
        for minor in range(10, -1, -1):
            if major == 2 and minor < 2:
                continue
            rizom_reg_path = f"SOFTWARE\\Rizom Lab\\RizomUV VS RS 202{major}.{minor}"
            try:
                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, rizom_reg_path)
                exe_path = winreg.QueryValue(key, "rizomuv.exe")
                return os.path.dirname(exe_path)
            except FileNotFoundError:
                pass
    return None


def remove_from_path(path: str):
    """Clear the given path from the python path.

    Use to remove the RizomUVLink module from the python path.

    Args:
    ----
        path (str): Path to the module to remove.

    """
    if path in sys.path:
        sys.path.remove(path)


def set_rizomlink_availability(prefs: "RizomUVBridgePreferences", rizom_dir: Path) -> bool:
    """Handle the users ability to access the RizomUVLink module.

    If the module isn't available disable the ability to attempt a
    connection. Can be used to hide parts of the UI so user cannot
    try to connect when it is unavailable.

    Checks:
    - macOS (Windows only)
    - Library not present with Rizom install
    - Python version not supported

    Args:
    ----
        prefs (RizomUVBridgePreferences): Addon preferences

    Returns:
    -------
        bool: True if the RizomUVLink module exists and can be imported, False otherwise

    """
    if platform.system() != "Windows":
        prefs.livelink_allowed = False
        print("RizomUV Bridge: RizomUVLink disabled.")
        print(f"RizomUVLink Not supported on {platform.system()}")
        return False

    native_link_dir = rizom_dir.parent / "RizomUVLink"
    if not native_link_dir.exists():
        prefs.livelink_allowed = False
        print("RizomUV Bridge: RizomUVLink disabled.")
        print("RizomUVLink library not found with RizomUV.")
        return False

    sys.path.append(constants.RIZOMUV_LINK_PACKAGE)
    try:
        # Try importing it to find out if it is a compatible version
        importlib.util.find_spec("RizomUVLink")

        prefs.livelink_allowed = True
        print("RizomUV Bridge: RizomUVLink is available.")
        return True

    except (ModuleNotFoundError, TypeError):
        remove_from_path(constants.RIZOMUV_LINK_PACKAGE)

        prefs.livelink_allowed = False
        print("RizomUV Bridge: RizomUVLink disabled.")
        print("RizomUVLink failed to import, likely incompatible Python version.")
        return False


def is_windows_app_install() -> bool:
    """Check if the users Blender version is from the Windows Store.

    Needed because when Blender is installed in the WindowsApps
    directory, it is not possible to write to the data files inside
    the addon in this protected directory.

    The normal Blender installation installs addons inside AppData
    which is writable.


    Returns
    -------
        bool: True if the users Blender version is from the Windows Store.

    """
    executable_path = sys.executable
    if "WindowsApps" in executable_path:
        return True
    return False


def setup_data_directory() -> None:
    """Create the data directory if it does not exist.

    - Windows only, macOS defaults to the addon folder.

    Args:
    ----
        prefs (RizomUVBridgePreferences): Addon preferences.

    """
    base_path = Path(constants.DATA_PATH)

    # Ensure directories exist
    os.makedirs(base_path, exist_ok=True)
    os.makedirs(base_path / "mesh_files", exist_ok=True)

    # Ensure data exist
    for file_name in [
        "rizom_ports.txt",
        "rizom_session.json",
        "rizom_output.json",
        "blender_output.json",
    ]:
        (base_path / file_name).touch()


def file_exists(path: str) -> bool:
    """Check if the given file exists.

    Args:
    ----
        path (str): Path to the file.

    Returns:
    -------
        bool: True if the file exists, False otherwise.

    """
    return Path(path).is_file()


def get_path_with_doublesep(path: Path | str) -> str:
    """Get the path as a string with backslashes replaced by double backslashes."""
    if isinstance(path, Path):
        str_path = str(path)
        return str_path.replace("\\", "\\\\")

    return path.replace("\\", "\\\\")
