# -*-coding:utf-8-*-
import traceback

from utils.common import log as logger
from utils.common.error.fcd_error_code import get_code_msg
from plugins.DistributedStorage.params.install_params_checkutils import ManageStorageParamsCheckUtils
from plugins.DistributedStorage.params.install_params_checkutils import PoolCheck


def param_check(**kwargs):
    """
    插件参数校验接口函数
    :param kwargs:
    :return: 成功：True, ''， 失败：False，
            错误信息，格式：{key1:err_msg1, key2:err_msg2}
    """
    error_params = {}
    try:
        params = kwargs["params"]
        project_id = params["project_id"]
        fs_server_list = params.get("fs_server_list", '')
        logger.info("ManageStorFBParamCheckHook: Start to check the parameters: fs_server_list")
        ret, detail = ManageStorFBParamCheckHook().check(project_id, fs_server_list)
        logger.info('param_list check status: %s, output: %s' % (ret, detail))
        if not ret:
            error_params.update(detail)
        if error_params:
            return False, error_params
        if not ret:
            error_params.update(detail)
    except Exception as e:
        logger.error("FS800Exp params check is abnormal：{}".format(e))
        logger.error(traceback.format_exc())
        error_params['params check'] = "The script is abnormal."
        return False, error_params


class ManageStorFBParamCheckHook(object):

    def check(self, project_id, input_params):
        if not input_params:
            return True, ''
        error_msg_dict = {}
        err_msg_dict = self.check_manage_and_ha_param(project_id, input_params)
        error_msg_dict.update(err_msg_dict)
        if error_msg_dict:
            return False, error_msg_dict
        return True, ''

    @staticmethod
    def check_converge_pool_disk_num(pool, server_list):
        pool_check = PoolCheck()
        for server in server_list:
            if not ("first_node" in server["bmc_role"] or "controller" in server["bmc_role"] or
                    ("cloud_service" in server["bmc_role"] and "osd" in server["ref_component"])):
                continue
            disk_slot = server["primary_slot"]
            if disk_slot:
                disk_num = int(disk_slot.split('-')[1]) - int(disk_slot.split('-')[0]) + 1
                pool_check.record_disk_num(disk_num)
        return pool_check.check_disk_num(pool)

    def check_manage_and_ha_param(self, project_id, input_params):
        err_msg_dict = {}
        dc002_zk_node_num = 0
        dc002_zk_slot = ""
        dc002_primary_capacity = 0
        dc002_cache_capacity = 0
        dc002_site = "dc002"
        dc002_cache_type = None
        for param_item in input_params:
            if not ("first_node" in param_item["bmc_role"] or "controller" in param_item["bmc_role"] or
                    ("cloud_service" in param_item["bmc_role"] and "osd" in param_item["ref_component"])):
                continue
            if dc002_site == param_item.get("site"):
                if param_item.get("is_metadata_node") == '1':
                    dc002_zk_node_num += 1
                    # zk槽位检测
                    dc002_zk_slot, msg_dict = self.check_zk_slot(
                        param_item, err_msg_dict, dc002_site, "managestorfb_dc002_zk_slot", dc002_zk_slot)
                    err_msg_dict.update(msg_dict)
                # 主存槽位的检测
                msg_dict = ManageStorageParamsCheckUtils.dc_check_primary_slot(
                    param_item, err_msg_dict, dc002_site, "managestorfb_dc002_primary_slot")
                err_msg_dict.update(msg_dict)
                # 主存盘容量的检测
                dc002_primary_capacity, msg_dict = ManageStorageParamsCheckUtils.dc_check_primary_capacity(
                    param_item, err_msg_dict, dc002_site, "managestorfb_dc002_primary_capacity", dc002_primary_capacity)
                err_msg_dict.update(msg_dict)
                # 缓存类型检查
                dc002_cache_type, msg_dict = ManageStorageParamsCheckUtils.dc_check_cache_type(
                    param_item, self.manage_cache_type, dc002_cache_type, dc002_site, err_msg_dict,
                    "managestorfb_dc002_cache_type")
                err_msg_dict.update(msg_dict)
                # 缓存总容量(GB)的检测
                dc002_cache_capacity, msg_dict = ManageStorageParamsCheckUtils.dc_check_cache_capacity(
                    param_item, err_msg_dict, dc002_site, dc002_cache_capacity,
                    "managestorfb_dc002_cache_capacity", "managestorfb_dc002_cache_type")
                err_msg_dict.update(msg_dict)

                # 元数据槽位与主存槽位冲突检查
                msg_dict = self.zk_slot_and_primary_slot_conflict_check(
                    param_item, dc002_site, "managestorfb_dc002_primary_slot", "managestorfb_dc002_zk_slot",
                    err_msg_dict)
                err_msg_dict.update(msg_dict)
            # 控制节点的指定部署组件必须包含osd组件
            if "osd" not in param_item["ref_component"]:
                err_msg_dict["managestorfb_ref_component"] = get_code_msg('626242')

            if param_item.get("is_metadata_node") != "1":
                    err_msg_dict["managestorfb_dc002_is_metadata_node"] = get_code_msg('626237') % dc002_site

            # 元数据节点个数做检测
            if dc002_zk_node_num not in [3, 5, 7] and "managestorfb_dc002_is_metadata_node" not in err_msg_dict:
                err_msg_dict["managestorfb_dc002_is_metadata_node"] = \
                    get_code_msg('626250') % (dc002_site, dc002_zk_node_num)
        # 检查site1存储池中服务器上盘的数量是否满足要求
        check_result = ManageStorageParamsCheckUtils.check_region_ha_pool_disk_num(dc002_site, dc002_site, input_params)
        if check_result:
            err_msg_dict.update(check_result)

        return err_msg_dict

    @staticmethod
    def check_zk_slot(param_item, err_msg_dict, site_name, key_name, zk_slot):
        msg_dict = {}
        # zk槽位空值检测
        if param_item["zk_slot"]:
            if not str(param_item["zk_slot"]).isdigit() and key_name not in err_msg_dict:
                # zk节点zk槽位格式检测
                msg_dict[key_name] = get_code_msg('626239') % site_name
            elif not zk_slot:
                zk_slot = param_item["zk_slot"]
            elif zk_slot != param_item["zk_slot"] and key_name not in err_msg_dict:
                # zk节点zk槽位一致性检测
                msg_dict[key_name] = get_code_msg('626240') % site_name
        return zk_slot, msg_dict

    @staticmethod
    def zk_slot_and_primary_slot_conflict_check(param_item, site, primary_key, zk_key, error_dict):
        msg_dict = {}
        if primary_key in error_dict or zk_key in error_dict:
            return error_dict
        zk_slot = param_item.get("zk_slot")
        if not zk_slot:
            return msg_dict
        primary_slot = param_item.get("primary_slot")
        primary_slot_start, primary_slot_end = primary_slot.split('-')
        if int(primary_slot_start) <= int(zk_slot) <= int(primary_slot_end):
            msg_dict["managestorfb_conflict_slot"] = get_code_msg("626239") % site
        return msg_dict
