# coding=UTF-8
# Copyright (c) 2025 Huawei Technologies Co., Ltd
import json
import os.path
import shutil

import utils

log = utils.stream_logger()


def build_gtest(root_dir, job_num):
    build_functionsystem(root_dir, job_num, build_type="Debug", gtest=True)


def build_binary(root_dir, job_num, version, build_type="Release", component="all", linker="auto",
                 cmake_args: dict[str, str] = None):
    build_functionsystem(
        root_dir,
        job_num,
        version=version,
        build_type=build_type,
        component=component,
        linker=linker,
        cmake_args=cmake_args,
    )


def build_functionsystem(
        root_dir,
        job_num,
        version="0.0.0",
        build_type="Debug",
        time_trace=False,
        coverage=False,
        jemalloc=False,
        sanitizers=False,
        gtest=False,
        component="all",
        linker="auto",
        cmake_args: dict[str, str] = None,
):
    log.info("Build cpp code in functionsystem")

    # 拷贝 proto 文件(proto/inner 已合并至 proto/posix,仅需复制 posix)
    log.info("Auto copy all proto file to cpp common folder")
    posix_proto = os.path.join(root_dir, "proto", "posix")
    cpp_proto_dir = os.path.join(root_dir, "functionsystem", "src", "common", "proto", "posix")
    shutil.copytree(posix_proto, cpp_proto_dir, copy_function=utils.copy2_when_modify, dirs_exist_ok=True)

    # 使用 CMake 创建 Ninja 构建清单
    root_dir = os.path.abspath(root_dir)  # Git根目录
    code_path = os.path.join(root_dir, "functionsystem")
    output_dir = os.path.join(code_path, "output")
    build_dir = os.path.join(code_path, "build")

    if cmake_args is None:
        cmake_args = {}
    cmake_args.update({
        "BUILD_VERSION": version_name(version),
        "CMAKE_INSTALL_PREFIX": output_dir,
        "CMAKE_BUILD_TYPE": build_type,
        "SANITIZERS": bool2switch(sanitizers),
        "BUILD_LLT": bool2switch(gtest),
        "BUILD_GCOV": bool2switch(coverage),
        "BUILD_THREAD_NUM": job_num,
        "ROOT_DIR": root_dir,  # 为了数据系统路径
        "JEMALLOC_PROF_ENABLE": bool2switch(jemalloc),
        "FUNCTION_SYSTEM_BUILD_TARGET": component,
        "FUNCTION_SYSTEM_BUILD_LINKER": linker,
        "FUNCTION_SYSTEM_BUILD_TIME_TRACE": bool2switch(time_trace),
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
    })
    cmake_generate(code_path, build_dir, cmake_args)

    # 使用 Ninja 编译程序
    ninja_make(build_dir, str(job_num), component)

    # 使用 CMake 完成产物复制
    cmake_install(build_dir)


def cmake_generate(source_dir, build_dir, cmake_args: dict[str, str]):
    log.info(f"CMAKE generate Ninja make list with args: {json.dumps(cmake_args)}")
    log.info(f"Run cmake with source code[{source_dir}] to build[{build_dir}]")
    args = []
    for key, val in cmake_args.items():
        k = "-D" + key.upper()
        v = val if val is not None else ""
        args.append(f"{k}={v}")
    utils.sync_command(["cmake", "-G", "Ninja", "-S", source_dir, "-B", build_dir, *args])


def ninja_make(build_dir: str, job_num: str, component: str = "all"):
    log.info(f"Run Ninja build in dir[{build_dir}] using {job_num} cores. Module: {component}")
    command = ["ninja", "-C", build_dir, "-j", job_num]
    if component != "all":
        command.append(component)
    utils.sync_command(command)


def cmake_install(build_dir: str):
    log.info(f"Run cmake install in dir[{build_dir}]")
    utils.sync_command(["cmake", "--build", build_dir, "--target", "install"])


def version_name(version):
    return f"yr-functionsystem-v{version}"


def bool2switch(b: bool):
    return "ON" if b else "OFF"