# Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.

import os
import time
import ctypes
from pathlib import Path

_DEFUALT_KCAL_LIB_PATH = "/usr/local/lib"
_KCAL_LIBS = [
    "libdata_guard_common.so",
    "libdata_guard.so",
    "libhitls_bsl.so",
    "libhitls_crypto.so",
    "libmpc_tee.so",
    "libsecurec.so",
]


def preload_lib():
    kcal_lib_path = os.getenv("KCAL_LIB_PATH", _DEFUALT_KCAL_LIB_PATH)

    if not os.path.isdir(kcal_lib_path):
        raise FileNotFoundError(f"kcal lib path is not exist: {kcal_lib_path}")

    if not os.path.isabs(kcal_lib_path):
        raise ValueError(f"The kcal lib path {kcal_lib_path} must be an absolute path.")

    # 添加自定义目录到链接库搜索路径
    if kcal_lib_path != _DEFUALT_KCAL_LIB_PATH:
        old_ld = os.environ.get("LD_LIBRARY_PATH", "")
        os.environ["LD_LIBRARY_PATH"] = kcal_lib_path + os.pathsep + old_ld

    # 加载 kcal 动态链接库
    failed_files = []
    for kcal_lib_name in _KCAL_LIBS:
        kcal_lib_abs_path = os.path.join(kcal_lib_path, kcal_lib_name)
        if not os.path.isfile(kcal_lib_abs_path):
            raise FileNotFoundError(
                f"kcal lib {kcal_lib_name} is not in {kcal_lib_path}"
            )

        try:
            ctypes.CDLL(kcal_lib_abs_path, mode=ctypes.RTLD_GLOBAL)
            print(f"Preloaded {kcal_lib_abs_path} (RTLD_GLOBAL)")
        except OSError as e:
            failed_files.append(kcal_lib_abs_path)

    for _ in range(15):
        if failed_files:
            for so_file in failed_files:
                time.sleep(0.1)
                try:
                    ctypes.CDLL(str(so_file), mode=ctypes.RTLD_GLOBAL)
                    print(f"Preloaded {so_file} (RTLD_GLOBAL)")
                    failed_files.remove(so_file)
                except OSError as e:
                    print(f"Failed to load {so_file} {e}")
                    continue

    if failed_files:
        raise RuntimeError(f"kcal {failed_files} so lib failed to load")