# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import json

import utils.common.log as logger
from utils.DBAdapter.DBConnector import BaseOps
from utils.business.project_util import ProjectApi
from utils.business.project_condition_utils import get_project_conditions
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant
from plugins.DistributedStorage.Deploy.scripts.PreCheck.common.device_operate \
    import PreCheckOperate, PreCheckPublicOperate


class StorageNodeOsPackageCheck(object):
    """
    更新inspect.json文件，保证上传的存储os包与实际的cpu架构一致：
    1. 查找存储节点bmc_ip的CPU架构
    2. 删除原inspect.json文件里的os包信息
    3. 将与节点实际的cup架构匹配的os包信息（json_data）更新到inspect.json文件中
    4. 在数据库中更新inspect.json。
    """
    def __init__(self, project_id, pod_id):
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = BaseOps()
        self.pre_check_pub_opr = PreCheckPublicOperate(project_id, pod_id)

    @classmethod
    def modify_json_data(cls, json_path, arch_set, project_condition):
        need_pkgs = list()
        for arch_tmp in arch_set:
            if arch_tmp == 'X86':
                need_pkgs.append(DeployConstant.STORAGE_PACKAGES_PATTERN[2])
            if arch_tmp == 'ARM':
                need_pkgs.append(DeployConstant.STORAGE_PACKAGES_PATTERN[3])
        logger.info('Modify the file: inspect.json')
        pkg_index = set()
        pkg_delete = list()
        with open(json_path, 'r', encoding='utf-8') as file_inspect_json:
            json_dict = json.load(file_inspect_json)
        pkg_define_list = json_dict.get('pkg_define')
        for i, pkg_info in enumerate(pkg_define_list):
            pkg_name_tmp = pkg_info.get('pkgs')
            for each_pkg in pkg_name_tmp:
                if each_pkg.get('OceanStor-Pacific_8.1.*_OS-*x86*64*.tgz', '') or \
                        each_pkg.get('OceanStor-Pacific_8.1.*_OS-*aarch64*.tgz', ''):
                    pkg_index.add(i)
        for j in pkg_index:
            pkg_delete.append(pkg_define_list[j])
        for tmp in pkg_delete:
            json_dict.get('pkg_define').remove(tmp)
        logger.info("Update the package information to the 'inspect.json'")
        json_data = {"project_condition": project_condition, "pkgs": need_pkgs}
        json_dict['pkg_define'].append(json_data)
        PreCheckOperate.update_json_file(json_path, json_dict)

    def get_condition(self):
        _condition = get_project_conditions(self.project_id)
        logger.info(f'project  conditions is {_condition}')
        project_condition = []
        for k, v in _condition.items():
            if v:
                project_condition.append(k)
        project_condition.append("!TenantStorFB_Heterogeneous")
        project_condition = '&'.join(project_condition)
        return project_condition

    def procedure(self):
        logger.info('Start to update the file: inspect.json')

        json_path = self.pre_check_pub_opr.get_fs_inspect_json_path()
        logger.info("Get plugin path:%s" % json_path)

        # 遍历节点，获取节点cpu架构
        logger.info('Query the CPU architecture of stroage node')
        arch_set = self.get_cpu_set()

        # 获取工程条件
        project_condition = self.get_condition()

        # 创建需要校验的os包信息列表
        logger.info('Creating a list of package information corresponding to the CPU architecture')
        self.modify_json_data(json_path, arch_set, project_condition)

        # 将inspect.json文件更新入数据库
        logger.info('Add package information to db')
        ProjectApi.update_project_pkg_verify_status(self.project_id, False)

        logger.info('Update completed!!!')

    def get_cpu_set(self):
        arch_all = ('X86', 'ARM')
        arch_set = set()
        node_info = self.db.get_install_os_list_info(self.pod_id) + \
            self.db.get_install_os_list_info(self.pod_id, 'rep')
        bmc_ip_list = [node.get('bmc_ip') for node in node_info]
        cpu_arch_dict = PreCheckOperate.get_system_arch(bmc_ip_list)
        for node in node_info:
            bmc_ip = node.get('bmc_ip')
            arch = cpu_arch_dict.get(bmc_ip).get('stdout')
            if arch not in arch_all:
                err_msg = 'Failed: The actual CPU architecture of the node {}：{}'.format(bmc_ip, arch)
                logger.error(err_msg)
                raise Exception(err_msg)
            arch_set.add(arch)
        return arch_set
