# -*-coding:utf-8-*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import json
import pathlib
import re
import os
import stat
from configparser import ConfigParser

from utils.common import log as logger
from utils.DBAdapter.DBConnector import BaseOps
from utils.constant.path_constant import ProjectPluginsPath
from utils.business.project_condition_utils import get_project_conditions, get_project_condition_boolean
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc
from plugins.DistributedStorage.logic.deploy_operate import DeployOperate
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant


class PreCheckOperate(object):
    @classmethod
    def update_json_file(cls, json_path, stream):
        """不存在创建json文件，存在则清空内容后写入stream"""
        flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
        modes = stat.S_IWUSR | stat.S_IRUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP
        with os.fdopen(os.open(json_path, flags, modes), 'w') as f:
            json.dump(stream, f, indent=2, ensure_ascii=False)

    @classmethod
    def get_system_arch(cls, bmc_ip_list):
        """
        minios中获取分离部署存储节点CPU架构存入json文件
        :return:
        """
        cmd = "uname -p"
        cmd_exe = BMCCmdExc()
        bmc_ip_list = list(set(bmc_ip_list))
        result_all = cmd_exe.run(bmc_ip_list, cmd)
        logger.info("Exec cmd: %s, result: %s" % (cmd, result_all))
        for bmc_ip in bmc_ip_list:
            result = result_all[bmc_ip]['stdout']
            ret_arch_list = re.findall('x86_64|aarch64', result)
            if len(ret_arch_list) == 1:
                ret_arch = ret_arch_list[0]
            else:
                err_msg = "Failed query cpu arch, cmd result:%s find:%s" % (result, ret_arch_list)
                logger.error(err_msg)
                raise Exception(err_msg)
            if ret_arch == 'x86_64':
                serv_cpu_arch = 'X86'
            elif ret_arch == 'aarch64':
                serv_cpu_arch = 'ARM'
            else:
                serv_cpu_arch = 'Unkown'
                err_msg = "Failed get processor type, cmd result:%s find:%s" % (result, serv_cpu_arch)
                logger.error(err_msg)
                raise Exception(err_msg)
            logger.info("Processor type:%s" % serv_cpu_arch)
            result_all[bmc_ip]['stdout'] = serv_cpu_arch
        cpu_arch_file = DeployConstant.CPU_ARCH_FILE_FOR_INSTALL_OS.format(ProjectPluginsPath.project_plugins_path())
        cls.update_json_file(cpu_arch_file, result_all)
        return result_all

    @classmethod
    def get_1880_raid_node(cls, bmc_ip_list):
        cmd = "lspci |grep -v grep|grep RAID.*3758"
        cmd_exe = BMCCmdExc()
        bmc_ip_list = list(set(bmc_ip_list))
        result_all = cmd_exe.run(bmc_ip_list, cmd)
        logger.info("Exec cmd: %s, result: %s" % (cmd, result_all))
        for bmc_ip in bmc_ip_list:
            is_1880 = False
            result = result_all.get(bmc_ip).get('stdout')
            if re.search("RAID.*3758", result):
                is_1880 = True
            result_all.get(bmc_ip)['is_1880'] = is_1880
        return result_all

    @classmethod
    def get_3152_raid_node(cls, bmc_ip_list: list):
        cmd_exe = BMCCmdExc()
        cmd = DeployConstant.DRIVER_TYPE_CONDITION.get("bp3152").get("cmd")
        result_all = cmd_exe.run(bmc_ip_list, cmd)
        logger.info("Exec cmd: %s, result: %s" % (cmd, result_all))
        for bmc_ip in bmc_ip_list:
            result = result_all.get(bmc_ip).get('stdout')
            pattern = DeployConstant.DRIVER_TYPE_CONDITION.get("bp3152").get("pattern")
            result_all.get(bmc_ip)['is_bp3152'] = True if re.search(pattern, result) else False
        return result_all


class PreCheckPublicOperate:
    def __init__(self, project_id, pod_id, *args, **kwargs):
        self.project_id = project_id
        self.pod_id = pod_id
        self.args = args
        self.kwargs = kwargs
        self.database = BaseOps()

    @classmethod
    def get_cfg_info(cls):
        plugin_path = ProjectPluginsPath.project_plugins_path()
        cfg_path = str(pathlib.Path(plugin_path) / pathlib.Path("DistributedStorage/utils/common/config.ini"))
        cfg = ConfigParser()
        cfg.read(cfg_path)
        return cfg

    @classmethod
    def get_plugins_version(cls):
        cfg = cls.get_cfg_info()
        plugins_version = cfg.get("plugins_version", "plugins_version")
        logger.info("plugins_version: {}".format(plugins_version))
        return plugins_version

    @classmethod
    def get_product_version(cls, float_ip, portal_pwd):
        opr = DeployOperate(float_ip=float_ip)
        opr.login(DeployConstant.DM_LOGIN_USER, portal_pwd)
        try:
            _, rsp_data = opr.get_product()
        finally:
            opr.logout()
        product_version = rsp_data.get("version")
        logger.info('Pacific Version: {}'.format(product_version))
        return product_version

    @classmethod
    def filter_3980_raid_node(cls, bmc_ip_list: list, cmd_exe_obj: BMCCmdExc):
        check_cmd = r"""if [ -n "`lspci | grep SAS39xx`" ]; then echo 'yes'; fi"""
        cmd_result = cmd_exe_obj.run(bmc_ip_list, check_cmd)
        remain_list, node_3908 = [], []
        for bmc_ip in bmc_ip_list:
            if 'yes' in cmd_result.get(bmc_ip).get("stdout"):
                logger.info(f'This is 3908 RAID Node. bmc ip:{bmc_ip}')
                node_3908.append(bmc_ip)
                continue
            remain_list.append(bmc_ip)

        return remain_list, node_3908

    def get_bmc_info(self, need_rep=False):
        ret = []
        all_bmc_info = self.database.get_install_os_list_info(self.pod_id)
        if need_rep:
            all_bmc_info.extend(self.database.get_install_os_list_info(self.pod_id, component="rep"))
        all_bmc_ip = set()
        for node_info in all_bmc_info:
            if node_info.get("bmc_ip") not in all_bmc_ip:
                ret.append(node_info)
                all_bmc_ip.add(node_info.get("bmc_ip"))
        return ret

    def get_condition(self):
        _condition = get_project_conditions(self.project_id)
        project_condition = []
        for key, value in _condition.items():
            if value:
                project_condition.append(key)
        project_condition.append("!TenantStorFB_Heterogeneous")
        return '&'.join(project_condition)

    def get_fs_inspect_json_path(self):
        plugin_path = ProjectPluginsPath.project_plugins_path()
        if get_project_conditions(self.project_id).get('ProjectDeploy'):
            scenario_path = 'Deploy'
        elif get_project_conditions(self.project_id).get('ExpansionAdCloudService'):
            scenario_path = 'Replication'
        else:
            scenario_path = 'Expansion'
        json_path = r"{}/DistributedStorage/{}/params/inspect.json".format(plugin_path, scenario_path)
        return json_path

    def get_third_inspect_json_path(self):
        exp_scale_condition = 'ExpansionScale_CloudServiceNode|ExpansionNetworkRes_NetworkNode|(Type2&FusionELB)'
        plugin_path = ProjectPluginsPath.project_plugins_path()
        if get_project_condition_boolean(self.project_id, exp_scale_condition):
            json_path = r"{}/ResourceCheck/workflow/expansionscale/params/inspect.json".format(plugin_path)
        else:
            json_path = r"{}/ResourceCheck/workflow/deploy/params/inspect.json".format(plugin_path)
        return json_path
