import os
import sys
import time
import uuid
import winreg
from ctypes.wintypes import RECT

import psutil
import win32gui
import winshell
import ctypes
import pythoncom
import win32com.client

import win32api
from comtypes.typeinfo import LoadTypeLibEx
from ctypes import OleDLL, c_void_p, byref, WINFUNCTYPE
from uuid import UUID
from tools.log import logger

class Utils:
    @staticmethod
    def extract_between_strings(content, start_tag, end_tag):
        """
        提取content中从start_tag到end_tag之间的字符串。

        参数:
            content (str): 包含要提取内容的字符串。
            start_tag (str): 起始标记字符串。
            end_tag (str): 结束标记字符串。

        返回:
            str: start_tag和end_tag之间的内容。如果未找到匹配内容，则返回空字符串。
        """
        try:
            # 查找起始标记的位置
            start_index = content.find(start_tag)
            if start_index == -1:
                return ""
            # 计算实际内容的起始位置
            start_index += len(start_tag)
            # 查找结束标记的位置
            end_index = content.find(end_tag, start_index)
            if end_index == -1:
                return ""
            # 提取中间的内容
            return content[start_index:end_index]
        except Exception as e:
            # 错误处理，返回空字符串或抛出异常
            return ""

    @staticmethod
    def get_registry_value(key_path, value_name,key=winreg.HKEY_CURRENT_USER):
        try:
            with winreg.OpenKey(key, key_path) as key:
                value, _ = winreg.QueryValueEx(key, value_name)
                return value
        except FileNotFoundError:
            return None

    @staticmethod
    def get_install_dir_from_shortcut(shortcut: str):
        try:
            with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                                r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders") as key:
                value, _ = winreg.QueryValueEx(key, "Desktop")
            shortcut = winshell.shortcut(os.path.join(value, shortcut))
            return shortcut.path
        except Exception as e:
            print(f"Error parsing shortcut {value + shortcut}: {e}")
            return None

    @staticmethod
    def makelong(low, high):
        return low | (high << 16)

    @staticmethod
    def set_window_position_and_size(hwnd, x, y, width, height):
        """
        设置指定窗口句柄的窗口的位置和大小。

        :param hwnd: 窗口句柄
        :param y: 窗口的新 y 坐标
        :param x: 窗口的新 x 坐标
        :param width: 窗口的新宽度
        :param height: 窗口的新高度
        """
        if hwnd:
            win32gui.MoveWindow(hwnd, x, y, width, height, True)
        else:
            logger.error("无效的窗口句柄")
            print("无效的窗口句柄")

    @staticmethod
    def get_window_position_and_size(hwnd):
        """
        获取指定窗口句柄的窗口的位置和大小。

        :param hwnd: 窗口句柄
        :return: 窗口的位置和大小
        """
        if hwnd:
            rect = win32gui.GetWindowRect(hwnd)
            x, y, width, height = rect
            return x, y, width-x, height-y
        else:
            raise Exception("无效的窗口句柄")

    @staticmethod
    def get_mac_address():
        mac_address = ':'.join(hex(uuid.getnode())[2:].zfill(12)[i:i + 2] for i in range(0, 12, 2))
        return mac_address

    @staticmethod
    def is_admin():
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except Exception:
            return False

    @staticmethod
    def run_as_admin():
        # 以管理员权限重新运行当前脚本
        script = sys.argv[0]
        params = ' '.join([f'"{param}"' for param in sys.argv[1:]])
        try:
            ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, f'"{script}" {params}', None, 1)
        except Exception as e:
            print(f"Failed to elevate privileges: {e}")
            sys.exit(1)

    class TimedLock:
        def __init__(self, lock, timeout):
            self.lock = lock
            self.timeout = timeout

        def __enter__(self):
            """尝试获取锁，如果在超时内无法获取，抛出 TimeoutError"""
            if not self.lock.acquire(timeout=self.timeout):
                raise TimeoutError(f"Could not acquire lock within {self.timeout} seconds.")
            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            """确保锁被释放"""
            self.lock.release()

    @staticmethod
    class Timer:
        def __init__(self):
            self._time_signs = {}

        def time_sign(self, sign):
            self._time_signs[sign] = time.time()

        def timer(self, sign, t):
            if sign not in self._time_signs:
                self._time_signs[sign] = time.time()
                return True
            if time.time() - self._time_signs[sign] > t:
                self._time_signs[sign] = time.time()
                return True
            return False

    @staticmethod
    def create_instance_from_com_dll(dll_path):
        """从 DLL 中创建 COM 对象实例"""
        com_classfactory = c_void_p(0)
        try:
            # 加载 DLL 和类型库
            dll = OleDLL(dll_path)
            typelib = LoadTypeLibEx(dll_path)

            # 获取 COM 对象的 CLSID
            co_class_info = typelib.GetTypeInfo(1)
            co_class_attr = co_class_info.GetTypeAttr()
            clsid = UUID(str(co_class_attr.guid)).bytes_le

            # 获取 IClassFactory 接口
            iclassfactory = UUID(str(pythoncom.IID_IClassFactory)).bytes_le
            dll.DllGetClassObject(clsid, iclassfactory, byref(com_classfactory))

            # 从 IClassFactory 接口创建 COM 对象实例
            class_factory = pythoncom.ObjectFromAddress(com_classfactory.value, pythoncom.IID_IClassFactory)
            iptr = class_factory.CreateInstance(None, pythoncom.IID_IDispatch)
            return win32com.client.Dispatch(iptr, resultCLSID=None)

        except Exception as e:
            raise RuntimeError(f"Failed to create COM object from DLL: {e}")

        finally:
            # 释放 IClassFactory 接口
            if com_classfactory:
                IUnknown_Release = WINFUNCTYPE(c_void_p)(2, 'Release', (), pythoncom.IID_IUnknown)
                IUnknown_Release(com_classfactory)

    @staticmethod
    def draw_text_on_window(hwnd, text):
        print(text)
        # 获取窗口的设备上下文
        hdc = win32gui.GetDC(hwnd)

        # 设置文本颜色
        color = win32api.RGB(255, 0, 0)  # 红色
        ctypes.windll.gdi32.SetTextColor(hdc, color)
        ctypes.windll.gdi32.SetBkMode(hdc, 1)  # 透明背景

        # 在指定位置绘制文本
        x, y = 50, 50  # 文本的起始坐标
        ctypes.windll.gdi32.ExtTextOutW(hdc, x, y, 0, None, text, len(text), None)

        # 释放设备上下文
        win32gui.ReleaseDC(hwnd, hdc)

    @staticmethod
    def kill_process(pid):
        try:
            p = psutil.Process(pid)
            p.kill()  # 强制终止进程

            # 可选：等待进程结束，设置超时
            p.wait(timeout=3)  # 等待最多3秒
        except psutil.NoSuchProcess:
            logger.warning(f"Process {pid} does not exist.")
        except psutil.AccessDenied:
            logger.warning(f"Access denied to terminate process {pid}.")
        except psutil.TimeoutExpired:
            logger.warning(f"Process {pid} could not be terminated in time.")
        except Exception as e:
            logger.exception(f"Error: {e}")