import os
import sys
import logging

from shutil import copy
from os.path import join, normcase, normpath
from winreg import (
    OpenKeyEx, QueryValueEx, SetValueEx,
    HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS, KEY_READ
)

logger = logging.getLogger()

def is_frozen_exe() -> bool:
    return bool(getattr(sys, "frozen", False))

def update_service_binpath(service_name: str, exe_path: str) -> str:
    """
    Update service ImagePath in registry to point to exe_path.
    Returns the previous ImagePath string.
    """

    with OpenKeyEx(HKEY_LOCAL_MACHINE,
                       fr"SYSTEM\CurrentControlSet\services\{service_name}",
                       0,
                       KEY_ALL_ACCESS) as key:
        (old_executable, reg_type) = QueryValueEx(key, "ImagePath")
        SetValueEx(key, "ImagePath", None, 2, f'"{exe_path}"')

    return old_executable


def copy_running_exe(dest: str) -> bool:
    """
    Startup helper:
      - If the runnin executable is not 
        then copy it to dest (overwriting old dest if present),
      - Otherwise do nothing.

    Returns True if it performed changes, otherwise False.
    """
    # Where are we actually running from?
    current_exe = sys.executable

    # Windows paths are case-insensitive -> compare with normcase
    if normcase(current_exe) == normcase(dest):
        return False

    copy(current_exe, dest)
    return True

def servicePostUpdate(service_name, exe_path):
        logger.debug("Running exe %s", sys.executable)
        if is_frozen_exe() and copy_running_exe(exe_path):
            logger.debug("The running agent copyed to %s", exe_path)
            old_exe = update_service_binpath(service_name, exe_path)
            logger.debug("%s service binpath updated  %s -> %s", service_name, old_exe, exe_path)
            return True
        return False

def getRegistryVal(reg_path: str, name: str, default=None):
    """
    Read HKLM\\<reg_path>\\<name> and return its value.
    If key or value does not exist, return default.
    Example:
        getRegistryVal(
            r"SYSTEM\\CurrentControlSet\\Services\\circle-agent",
            "LogLevel",
            "INFO"
        )
    """
    value=default
    try:
        with OpenKeyEx(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ) as key:
            value, _ = QueryValueEx(key, name)
    except Exception as e: 
        logging.debug("Registry read failed %s\\%s: %s",
        reg_path, name, e
    )
    return value
        
def get_windows_version():
    if sys.platform != "win32":
        return None

    ver = sys.getwindowsversion()
    major = ver.major
    minor = ver.minor
    build = ver.build

    # Windows 7
    if major == 6 and minor == 1:
        return "Windows_7"

    # Windows 8 / 8.1
    if major == 6 and minor in (2, 3):
        return "Windows_8"

    # Windows 10 / 11
    if major == 10:
        # Windows 11 starts at build 22000
        if build >= 22000:
            return "Windows_11"
        else:
            return "Windows_10"

    return f"Windows_{major}_{minor}_{build})"

