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

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


class ManageStorFBParamCheckHook(object):
    def __init__(self):
        self.manage_cache_type = ['ssd_card', 'ssd_disk', 'none']

    @staticmethod
    def check_converge_pool_disk_num(pool, server_list):
        pool_check = PoolCheck()
        for server in server_list:
            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)

    @staticmethod
    def new_pool_component_check(err_msg_dict, param_item):
        # 新增管理存储池场景云服务节点的指定部署组件必须包含osd组件
        if "cloud_service" in param_item["bmc_role"] and "osd" not in param_item["ref_component"]:
            err_msg_dict["managestorfb_ref_component"] = get_code_msg('626242')

    @staticmethod
    def dc002_primary_check(dc002_primary_capacity, dc002_site, err_msg_dict, param_item):
        # 主存槽位的检测
        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)

    @staticmethod
    def dc001_primary_check(dc001_primary_capacity, dc001_site, err_msg_dict, param_item):
        # 主存槽位的检测
        msg_dict = ManageStorageParamsCheckUtils.dc_check_primary_slot(
            param_item, err_msg_dict, dc001_site, "managestorfb_dc001_primary_slot")
        err_msg_dict.update(msg_dict)
        # 主存盘容量的检测
        dc001_primary_capacity, msg_dict = ManageStorageParamsCheckUtils.dc_check_primary_capacity(
            param_item, err_msg_dict, dc001_site, "managestorfb_dc001_primary_capacity", dc001_primary_capacity)
        err_msg_dict.update(msg_dict)

    @staticmethod
    def osd_node_num_check(err_msg_dict, input_params):
        if len(input_params) < 3:
            err_msg = "The number of nodes in a storage pool cannot be less than 3."
            logger.error(err_msg)
            err_msg_dict["manage_storage_nodes"] = get_code_msg('626280')

    @staticmethod
    def check_pool_name(err_msg_dict, param_item):
        # 存储池名称检查
        if not param_item["manage_storage_pool_name"]:
            err_msg = "The name of storage pool in LLD can not be empty"
            logger.error(err_msg)
            err_msg_dict["manage_storage_pool_name"] = get_code_msg('626279') % "manage_storage_pool_name"

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

    def check_managestorfb_param(self, project_id, input_params):
        # 管理融合部署场景设备信息sheet页相关参数校验
        err_msg_dict = {}
        if get_project_condition_boolean(project_id, 'ManageStorFB80&!RegionConHA'):
            # 管理融合部署且不启用管理面跨AZ高可用场景相关参数校验
            err_msg_dict = self.check_managestorfb_and_not_regionconha_param(project_id, input_params)
        elif get_project_condition_boolean(project_id, 'ManageStorFB80&RegionConHA'):
            err_msg_dict = self.check_managestorfb_and_regionconha_param(project_id, input_params)
        return err_msg_dict

    def check_managestorfb_and_not_regionconha_param(self, project_id, input_params):
        err_msg_dict = {}
        primary_capacity = 0
        cache_capacity = None
        cache_type = None
        for param_item in input_params:
            # 扩管理节点场景非osd节点不做检查
            if get_project_condition_boolean(project_id, '!ManageStorNewPool'):
                if "osd" not in param_item["ref_component"]:
                    continue

            # 新增管理存储场景云服务节点的指定部署组件必须包含osd组件
            if "cloud_service" in param_item["bmc_role"]:
                if "osd" not in param_item["ref_component"]:
                    err_msg_dict["managestorfb_ref_component"] = get_code_msg('626241')

            # 存储池名称检查,扩管理节点存储池名称可以为空
            if get_project_condition_boolean(project_id, 'ManageStorNewPool'):
                self.check_pool_name(err_msg_dict, param_item)

            # 主存盘容量的检测
            logger.info("managestorfb: start to check primary capacity")
            primary_capacity, msg_dict = ManageStorageParamsCheckUtils.not_ha_primary_capacity_check(
                param_item, primary_capacity, err_msg_dict)
            err_msg_dict.update(msg_dict)
            logger.info("managestorfb: check primary capacity complete, result: {}".format(msg_dict))

            logger.info("managestorfb: start to check cache capacity")

            # 主存槽位的检测
            logger.info("managestorfb: start to check primary slot")
            msg_dict = ManageStorageParamsCheckUtils.not_ha_primary_slot_check(param_item, err_msg_dict)
            err_msg_dict.update(msg_dict)
            logger.info("managestorfb: check primary slot complete, result: {}".format(msg_dict))

            # 缓存类型和容量检查
            cache_type, cache_capacity, msg_dict = ManageStorageParamsCheckUtils.not_ha_cache_check(
                param_item, self.manage_cache_type, cache_type, cache_capacity, err_msg_dict)
            err_msg_dict.update(msg_dict)
            logger.info("managestorfb: check cache complete, result: {}".format(msg_dict))
        # 如果存在格式错误先返回，避免检测磁盘个数时脚本异常
        if err_msg_dict:
            return err_msg_dict
        input_params = [param for param in input_params if "osd" in param["ref_component"]]
        if get_project_condition_boolean(project_id, 'ManageStorNewPool'):
            self.osd_node_num_check(err_msg_dict, input_params)
            # 检查存储池中服务器上盘的数量是否满足要求
            check_result = self.check_converge_pool_disk_num('ManageStorage', input_params)
            err_msg_dict.update(check_result)
        return err_msg_dict

    def dc002_cache_check(self, args: collections.namedtuple):
        # 缓存类型检查
        dc002_cache_capacity, dc002_cache_type, dc002_site, err_msg_dict, param_item = args
        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)
        # 缓存容量检测
        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)

    def dc001_cache_check(self, *args):
        dc001_cache_capacity, dc001_cache_type, dc001_site, err_msg_dict, param_item = args
        # 缓存类型检查
        dc001_cache_type, msg_dict = ManageStorageParamsCheckUtils.dc_check_cache_type(
            *[param_item, self.manage_cache_type, dc001_cache_type, dc001_site, err_msg_dict,
              "managestorfb_dc001_cache_type"])
        err_msg_dict.update(msg_dict)
        # 缓存容量检测
        dc001_cache_capacity, msg_dict = ManageStorageParamsCheckUtils.dc_check_cache_capacity(
            *[param_item, err_msg_dict, dc001_site, dc001_cache_capacity,
              "managestorfb_dc001_cache_capacity", "managestorfb_dc001_cache_type"])
        err_msg_dict.update(msg_dict)

    def check_managestorfb_and_regionconha_param(self, project_id, input_params):
        err_msg_dict = {}
        dc001_primary_capacity = 0
        dc002_primary_capacity = 0
        dc001_cache_capacity = 0
        dc002_cache_capacity = 0
        dc001_site = "dc001"
        dc002_site = "dc002"
        dc001_cache_type = None
        dc002_cache_type = None
        for param_item in input_params:
            # 扩管理节点场景非osd节点不做检查
            if get_project_condition_boolean(project_id, '!ManageStorNewPool'):
                if "osd" not in param_item["ref_component"]:
                    continue
            self.check_pool_name(err_msg_dict, param_item)
            if dc001_site == param_item["site"]:
                self.dc001_primary_check(dc001_primary_capacity, dc001_site, err_msg_dict, param_item)
                self.dc001_cache_check(*[dc001_cache_capacity, dc001_cache_type, dc001_site, err_msg_dict, param_item])
            if dc002_site == param_item["site"]:
                self.dc002_primary_check(dc002_primary_capacity, dc002_site, err_msg_dict, param_item)
                args = collections.namedtuple(
                    'args', ["dc002_cache_capacity", "dc002_cache_type", "dc002_site", "err_msg_dict", "param_item"])
                params = args(dc002_cache_capacity, dc002_cache_type, dc002_site, err_msg_dict, param_item)
                self.dc002_cache_check(params)
            self.new_pool_component_check(err_msg_dict, param_item)
        input_params = [param for param in input_params if "osd" in param["ref_component"]]
        if get_project_condition_boolean(project_id, 'ManageStorNewPool'):
            self.osd_node_num_check(err_msg_dict, input_params)
        else:
            return err_msg_dict
        # 检查site1存储池中服务器上盘的数量是否满足要求
        check_result = ManageStorageParamsCheckUtils.check_region_ha_pool_disk_num(dc001_site, dc001_site, input_params)
        err_msg_dict.update(check_result)
        # 检查site2存储池中服务器上盘的数量是否满足要求
        check_result = ManageStorageParamsCheckUtils.check_region_ha_pool_disk_num(dc002_site, dc002_site, input_params)
        err_msg_dict.update(check_result)
        return err_msg_dict
