#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
from IPy import IP

from utils.business.project_condition_utils import get_project_conditions, \
    get_project_condition_boolean as cond_bool
from business.handler.param_template_handler.lld_template_handler.lld.lld_sheet_ui_basev2 import LldSheetUiBaseV2
from utils.DBAdapter.db_password import ParamPassword
from utils.common.param_check import check_param_ip
from utils.common import log as logger
from plugins.DistributedStorage.utils.common.fusion_storage_business_dao import FusionStorageBusinessDao
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant
from plugins.DistributedStorage.utils.common.deploy_constant import ServerList


class FusionStorageSeperateDeploySheet(LldSheetUiBaseV2):
    def __init__(self, **kwargs):
        super(FusionStorageSeperateDeploySheet, self).__init__(**kwargs)
        self.input_data = kwargs.get('basic_content')
        self.template_data = []
        self.fusionstorage_business_dao = FusionStorageBusinessDao(self.project_info, self.project_id)
        self.data = None
        self.col_show_dict = None

    def base_update_params(self, params_type: str, params: dict, **kwargs):
        """
        参数模板上传以及在线修改上传之后保存参数统一入口。基类需要实现此接口
        :param params_type: 参数类型
        :type params_type: str
        :param params: 参数
        :type params: dict
        :param kwargs: 扩展字段
        :type kwargs: dict
        :return: None/Exception
        :rtype:
        """
        try:
            kwargs = self.del_param_dao_type(**kwargs)
            self.fusionstorage_business_dao.update_params(params_type, params, **kwargs)
        except Exception as err:
            logger.error("Unexpected error occurs when update params. %s", str(err))

    def base_delete_params(self, params_type: str, params: dict, **kwargs):
        """
        在线修改参数功能的删除。基类需要实现此接口
        :param params_type: 参数类型
        :type params_type: str
        :param params: 参数
        :type params: dict
        :param kwargs: 扩展字段
        :type kwargs: dict
        :return: None/Exception
        :rtype:
        """
        try:
            kwargs = self.del_param_dao_type(**kwargs)
            self.fusionstorage_business_dao.delete_params_for_item(params_type, params, **kwargs)
        except Exception as err:
            logger.error("Unexpected error occurs when delete params item. %s", str(err))
            raise err

    def base_save_params(self, params_type: str, params: dict, **kwargs):
        """
        参数模板上传以及在线修改上传之后保存参数统一入口。基类需要实现此接口
        :param params_type: 参数类型
        :type params_type: str
        :param params: 参数
        :type params: dict
        :param kwargs: 扩展字段
        :type kwargs: dict
        :return: None/Exception
        :rtype:
        """
        try:
            kwargs = self.del_param_dao_type(**kwargs)
            self.fusionstorage_business_dao.save_params(params_type, params, **kwargs)
        except Exception as err:
            logger.error(
                "Unexpected error occurs when save params. %s" % str(err))
            raise err

    def base_query_params(self, **kwargs):
        """
        参数查询接口
        :param kwargs: 查询参数
        :type kwargs: dict
        :return: 参数
        :rtype: dict
        """
        try:
            kwargs = self.del_param_dao_type(**kwargs)
            return self.fusionstorage_business_dao.query_params(**kwargs)
        except Exception as err:
            logger.error(
                "Unexpected error occurs when query params. %s" % str(err))
            raise err

    def base_preprocess_params(self, params_type: str, params: dict, run_convert=False, param_dao_type=None):
        """
        参数预处理接口
        :param params_type: 参数类型
        :type params_type: str
        :param params: 参数
        :type params: dict
        :param run_convert:
        :type run_convert: bool
        :param param_dao_type:
        :type param_dao_type: str
        :return:
        :rtype:
        """
        try:
            self.fusionstorage_business_dao.preprocess_params(params_type, params, run_convert)
        except Exception as err:
            logger.error(
                "Unexpected error occurs when preprocess params. %s" % str(
                    err))
            raise err

    @staticmethod
    def set_template_col_show_condition_sub_1(cond, col_show_dict):
        is_cshastorage_tfb = cond.get('CSHAStorage_TFB')
        is_csdrstorage_tfb = cond.get('CSDRStorage_TFB')
        t_storfb_hete = cond.get('TenantStorFB_Heterogeneous')
        if not (is_cshastorage_tfb or is_csdrstorage_tfb):
            col_show_dict["deploy_component"] = False
            col_show_dict["replication_cluster_meta_info"] = False
            col_show_dict["replication_cluster_meta_type"] = False
        if t_storfb_hete:
            col_show_dict["management_plane"] = False
            col_show_dict["storage_plane"] = False
            col_show_dict["storage_inner_plane"] = False
        if not (not t_storfb_hete and (
                is_cshastorage_tfb or is_csdrstorage_tfb)):
            col_show_dict["replication_plane"] = False

    @staticmethod
    def get_down_list(cond, down_list_x86, down_list_arm, down_list_x86_odk, down_list_arm_odk):
        t_storfbreuse = cond.get('TenantStorFBReuse')
        exp_az = cond.get('ExpansionAZ')
        t_storfb_hete = cond.get('TenantStorFB_Heterogeneous')
        if t_storfb_hete:
            if exp_az and t_storfbreuse:
                equ_down_list = down_list_x86
            else:
                equ_down_list = down_list_x86 + down_list_arm
        else:
            if exp_az and t_storfbreuse:
                equ_down_list = down_list_x86_odk
            else:
                equ_down_list = down_list_x86_odk + down_list_arm_odk
        if 'GENERAL' not in equ_down_list:
            equ_down_list.append('GENERAL')
        return equ_down_list

    @staticmethod
    def _get_old_info_by_ip(data, is_tenantstorfb80_all, old_os_data):
        for new_fs_unit in data:
            if is_tenantstorfb80_all:
                if new_fs_unit.get('primary_slot'):
                    new_fs_unit['storagepool_slot'] = new_fs_unit.get(
                        'primary_slot')
            for old_fs_unit in old_os_data:
                if new_fs_unit.get("bmc_ip") != old_fs_unit["bmc_ip"]:
                    continue
                new_fs_unit["creuser"] = ParamPassword.saveback(
                    new_fs_unit["creuser"].get("creuser"),
                    old_fs_unit["creuser"])
                if new_fs_unit.get("bmc_passwd", None):
                    new_fs_unit["bmc_passwd"] = ParamPassword.saveback(
                        new_fs_unit["bmc_passwd"].get("bmc_passwd"),
                        old_fs_unit["bmc_passwd"])
                break

    def set_template_data(self, *args, **kwargs) -> list:
        preset_dicts = {}
        project_conditions = get_project_conditions(self.project_id)
        is_cshastorage_tfb = project_conditions.get('CSHAStorage_TFB')
        is_csdrstorage_tfb = project_conditions.get('CSDRStorage_TFB')
        is_projectdeploy = project_conditions.get('ProjectDeploy')
        is_drstorage_tfb_sep = project_conditions.get('DRStorage_TFB_Sep')
        is_expansionadcloudservice_2 = project_conditions.get(
            'ExpansionAdCloudService')
        is_tenantstorfbhci = project_conditions.get('TenantStorFBHCI')
        is_tenantstorfbhci80 = project_conditions.get('TenantStorFBHCI80')
        deploy_component_index = 'deploy_component'
        if is_cshastorage_tfb or is_csdrstorage_tfb:
            if is_drstorage_tfb_sep:
                if is_projectdeploy:
                    preset_dicts = {1: {deploy_component_index: 'rep_ctl'},
                                    2: {deploy_component_index: 'rep_ctl'},
                                    3: {deploy_component_index: 'rep_ctl'},
                                    4: {deploy_component_index: 'osd'},
                                    5: {deploy_component_index: 'osd'},
                                    6: {deploy_component_index: 'osd'}}
                if is_expansionadcloudservice_2:
                    preset_dicts = {1: {deploy_component_index: 'rep_ctl'},
                                    2: {deploy_component_index: 'rep_ctl'},
                                    3: {deploy_component_index: 'rep_ctl'}}
            if is_projectdeploy and not is_drstorage_tfb_sep:
                preset_dicts = {1: {deploy_component_index: 'osd,rep_ctl'},
                                2: {deploy_component_index: 'osd,rep_ctl'},
                                3: {deploy_component_index: 'osd,rep_ctl'},
                                4: {deploy_component_index: 'osd,rep'},
                                5: {deploy_component_index: 'osd,rep'},
                                6: {deploy_component_index: 'osd,rep'}}
            if is_drstorage_tfb_sep and (
                    is_tenantstorfbhci or is_tenantstorfbhci80):
                if is_projectdeploy or is_expansionadcloudservice_2:
                    preset_dicts = {1: {deploy_component_index: 'rep_ctl'},
                                    2: {deploy_component_index: 'rep_ctl'},
                                    3: {deploy_component_index: 'rep_ctl'}}
        final_data = []
        for _row_index, one_data_dict in preset_dicts.items():
            final_data.append(one_data_dict)
        self.template_data = final_data
        return final_data

    def set_summarising_data(self, *args, **kwargs) -> list:
        self.data = self.input_data.get("fusionstorage_business_server_list", []) if self.input_data else []
        return self.data

    def set_template_show_condition(self) -> bool:
        project_conditions = get_project_conditions(self.project_id)
        is_project_test = project_conditions.get('ProjectTest', 0)
        is_projectmodifaction = project_conditions.get('ProjectModifaction')
        is_projectmodifactioniam = project_conditions.get(
            'ProjectModifactionIAM')
        ipv4tipv46 = project_conditions.get(
            'ServiceIPV4tServiceIPV46')
        is_expansion_cloud_service = project_conditions.get(
            'ExpansionCloudService')
        is_expan_scale_network_bmsgw = project_conditions.get(
            'ExpansionNetworkRes_BMSGW')
        # 技术中台和AI数据中台服务订阅
        is_expan_service_storage = project_conditions.get(
            'ExpansionServiceStorage')
        show = False
        if not (is_project_test or (is_projectmodifaction and ipv4tipv46) or
                is_projectmodifactioniam):
            show = self.set_template_show_condition_sub(project_conditions)
            # 新增业务存储 工程
            if is_expan_service_storage:
                show = True
            # 技术中台和AI数据中台服务订阅
            elif is_expansion_cloud_service:
                show = False
            if is_expan_scale_network_bmsgw:
                show = False
        return show

    def set_template_show_condition_sub(self, project_conditions):
        is_dcupgradeproject61t631 = project_conditions.get(
            'DCUpgradeProject61t631')
        is_cshastorage_tfb = project_conditions.get('CSHAStorage_TFB')
        is_csdrstorage_tfb = project_conditions.get('CSDRStorage_TFB')
        is_drstorage_tfb_sep = project_conditions.get('DRStorage_TFB_Sep')
        is_tenantstorfbhci = project_conditions.get('TenantStorFBHCI')
        is_tenantstorfbhci80 = project_conditions.get('TenantStorFBHCI80')
        show = False
        if not is_dcupgradeproject61t631:
            if cond_bool(
                    self.project_id,
                    "((TenantStorFB | TenantStorFB80) &"
                    "ProjectDeploy) | (((TenantStorFB | TenantStorFB80) |"
                    "(TenantStorFBReuse |  TenantStorFBReuse80)) & "
                    "(ExpansionPOD_BMS | ExpansionPOD_KVM |"
                    "ExpansionAZ_KVM | ExpansionAZ_BMS))"):
                show = True
            if (is_cshastorage_tfb or is_csdrstorage_tfb) \
                    and is_drstorage_tfb_sep:
                show = True
            if (is_tenantstorfbhci or is_tenantstorfbhci80) \
                    and is_drstorage_tfb_sep:
                show = True
        return show

    def set_summarising_show_condition(self) -> bool:
        return self.set_template_show_condition()

    def set_summarising_col_show_condition(self) -> dict:
        return self.set_template_col_show_condition()

    def set_template_col_show_condition(self, *args, **kwargs) -> dict:
        col_show_dict = {}
        cond = get_project_conditions(self.project_id)
        is_cshastorage_tfb = cond.get('CSHAStorage_TFB')
        is_csdrstorage_tfb = cond.get('CSDRStorage_TFB')
        t_storfb_hete = cond.get('TenantStorFB_Heterogeneous')
        t_stor_back_sep = cond.get('TenantStorBackendNetSep')
        is_tenantstorfb80 = cond.get('TenantStorFB80')
        is_exp_service_storage = cond.get('ExpansionServiceStorage')
        self.set_template_col_show_condition_sub_1(cond, col_show_dict)
        if not t_storfb_hete:
            col_show_dict["manageIp"] = False
            col_show_dict["storageIp"] = False
            col_show_dict["storageInnerIp"] = False
        if (is_exp_service_storage and is_csdrstorage_tfb
                and not is_tenantstorfb80):
            col_show_dict['storage_pool_type'] = False
            col_show_dict['storage_pool_name_and_slot'] = False
        if not t_stor_back_sep:
            col_show_dict["storage_inner_plane"] = False
            col_show_dict["storageInnerIp"] = False
        if not (t_storfb_hete and is_cshastorage_tfb):
            col_show_dict["arbitration_plane_ip"] = False
        if not (t_storfb_hete and (is_cshastorage_tfb or is_csdrstorage_tfb)):
            col_show_dict["replication_plane_ip"] = False
        self._set_some_col_show(col_show_dict, cond)
        self.col_show_dict = col_show_dict
        return col_show_dict

    def set_down_list(self) -> dict:
        down_list_dict = {}
        cond = self.project_conditions
        t_storfb_hete = cond.get('TenantStorFB_Heterogeneous')
        exp_az = cond.get('ExpansionAZ')
        exp_pod = cond.get('ExpansionPOD')

        project_type = str(self.project_info.get("project_options", {}).get('project_type'))

        down_list_x86 = down_list_x86_odk = DeployConstant.LLD_DOWN_LIST_X86

        down_list_arm = ServerList.TaiShan2280_LIST + ServerList.TaiShan5280_LIST
        down_list_arm_odk = ServerList.TaiShan2280_LIST + ServerList.TaiShan5280_LIST
        if project_type == "ProjectDeploy":
            if t_storfb_hete:
                down_list_arm = ServerList.TaiShan2280_LIST + ServerList.TaiShan5280_LIST
            else:
                down_list_arm_odk = ServerList.TaiShan2280_LIST + ServerList.TaiShan5280_LIST
        if cond.get("ProjectExpansion") and (exp_az or exp_pod):
            if t_storfb_hete:
                down_list_arm = ServerList.TaiShan2280_LIST + ServerList.TaiShan5280_LIST
            else:
                down_list_arm_odk = ServerList.TaiShan2280_LIST + ServerList.TaiShan5280_LIST
        equ_down_list = self.get_down_list(cond, down_list_x86,
                                           down_list_arm, down_list_x86_odk, down_list_arm_odk)
        down_list_dict["equipment_model"] = equ_down_list

        # 业务存储商业模式上只支持EC
        if cond_bool(self.project_id,
                     "ExpansionAZ & TenantStorFBReuse"):
            storagepool_redundancy_policy_list_1_4 = ['3Redundancy']
        else:
            storagepool_redundancy_policy_list_1_4 = ['ec']
        down_list_dict[
            "storagepool_redundancy_policy"] = \
            storagepool_redundancy_policy_list_1_4
        return down_list_dict

    def set_comment(self) -> dict:
        is_tenantstorfb80 = self.project_conditions.get('TenantStorFB80')
        storagepool_redundancy_policy_comment = \
            self.lld_cfg.get_lld_param_value(
                'storagepool_redundancy_policy_comment') + \
            self.lld_cfg.get_lld_param_value(
                'osd_in_deploy_component_need_to_fill_in')
        storagepool_redundancy_policy_comment_80 = \
            self.lld_cfg.get_lld_param_value(
                'storagepool_redundancy_policy_comment_80') + \
            self.lld_cfg.get_lld_param_value(
                'osd_in_deploy_component_need_to_fill_in')

        if is_tenantstorfb80:
            storagepool_redundancy_policy_comment = \
                storagepool_redundancy_policy_comment_80

        comment_dict = {
            "storagepool_redundancy_policy":
                storagepool_redundancy_policy_comment}
        return comment_dict

    def read_data_from_excel_file(self, file_path, sheet_name="", file_sheet_data=None):

        '''
        获取 1.4华为分布式块存储分离部署参数
        :return:
        '''

        flag, data_list = super(FusionStorageSeperateDeploySheet,
                                self).read_data_from_excel_file(file_path,
                                                                sheet_name,
                                                                file_sheet_data)
        if not flag:
            return flag, data_list
        project_conditions = get_project_conditions(self.project_id)
        is_tenantstorfb80 = project_conditions.get('TenantStorFB80')
        is_tenantstorfbreuse80 = project_conditions.get('TenantStorFBReuse80')
        is_tenantstorfb80_all = is_tenantstorfb80 or is_tenantstorfbreuse80
        for item in data_list:
            if is_tenantstorfb80_all:
                if item.get('primary_slot'):
                    item['storagepool_slot'] = item.get('primary_slot')
            if not item.get('is_metadata_node', None):
                item['is_metadata_node'] = ""
            else:
                item['is_metadata_node'] = item.get('is_metadata_node', "")
            ec_block_size = item.get('ec_block_size')
            item['ec_block_size'] = ec_block_size if ec_block_size else 0
            fs_bmc_ip = item.get('bmc_ip')
            if fs_bmc_ip:
                is_ipv6 = check_param_ip(fs_bmc_ip, ip_version=6)
                item['bmc_ip'] = IP(fs_bmc_ip).strCompressed() if is_ipv6 else fs_bmc_ip

        return True, data_list

    def back_input_old_password_for_ui_data(self, data):
        pod_list = self.db_base.get_project_pods_by_id(self.project_id)
        for pod in pod_list:
            # 密码还原
            if len(data) == 0:
                continue
            is_tenantstorfb80 = self.project_conditions.get('TenantStorFB80')
            is_tenantstorfbreuse80 = self.project_conditions.get(
                'TenantStorFBReuse80')
            is_tenantstorfb80_all = is_tenantstorfb80 or is_tenantstorfbreuse80
            old_os_data = self.fusionstorage_business_dao.get_install_os_list_info(
                pod["pod_id"], 'all')
            self._get_old_info_by_ip(data, is_tenantstorfb80_all, old_os_data)

    def _set_some_col_show(self, col_show_dict, cond):
        is_expansion_az = cond.get('ExpansionAZ')
        is_tenantstorfb = cond.get('TenantStorFB')
        is_tenantstorfb80 = cond.get('TenantStorFB80')
        is_tenantstorfbreuse = cond.get('TenantStorFBReuse')
        is_tenantstorfbreuse80 = cond.get('TenantStorFBReuse80')
        if not ((is_tenantstorfb or is_tenantstorfb80) or (
                is_tenantstorfbreuse or is_tenantstorfbreuse80)):
            col_show_dict["is_metadata_node"] = False
            col_show_dict["storage_pool_name"] = False
            col_show_dict["storagepool_redundancy_policy"] = False
            col_show_dict["ec_ratio"] = False
            col_show_dict["ec_block_size"] = False
            col_show_dict["ec_cache"] = False
            col_show_dict["zk_slot"] = False
            col_show_dict["zk_type"] = False
            col_show_dict["storagepool_slot"] = False
            col_show_dict["primary_slot"] = False
            col_show_dict["primary_type"] = False
            col_show_dict["cache_type"] = False
        if not (is_tenantstorfb or is_tenantstorfbreuse):
            col_show_dict["storagepool_slot"] = False
        # fsb6.3时的EC的3个参数不再使用。
        col_show_dict["ec_ratio"] = False
        col_show_dict["ec_block_size"] = False
        col_show_dict["ec_cache"] = False
        # fsb8.False EC使用两个新的参数。
        if not (is_tenantstorfb80 or is_tenantstorfbreuse80):
            col_show_dict["ec_verify_fragments"] = False
            col_show_dict["ec_data_fragments"] = False
        if is_tenantstorfbreuse and is_expansion_az:
            col_show_dict["storage_pool_type"] = False
        if cond_bool(self.project_id,
                     "ExpansionAZ & TenantStorFBReuse80"):
            col_show_dict["is_metadata_node"] = False
            col_show_dict["zk_slot"] = False
            col_show_dict["zk_type"] = False
        if cond_bool(
                self.project_id,
                "ExpansionServiceStorage & (TenantStorNewPool | "
                "TenantStorNewNode)"):
            col_show_dict["is_metadata_node"] = False
            col_show_dict["zk_slot"] = False
            col_show_dict["zk_type"] = False
            col_show_dict["primary_slot"] = True
            col_show_dict["primary_type"] = True
            col_show_dict["cache_type"] = True
            col_show_dict["storagepool_redundancy_policy"] = True
            col_show_dict["ec_verify_fragments"] = True
            col_show_dict["ec_data_fragments"] = True
