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

import utils.common.log as logger
from utils.common.message import Message
from utils.common.fic_base import StepBaseInterface
from utils.common.exception import HCCIException
from utils.business.param_util import ParamUtil
from utils.security import crypt
from plugins.DistributedStorage.common.parameter_gain import ParamsGain
from plugins.DistributedStorage.common.constants import SERVICE_NAME
from plugins.DistributedStorage.logic.sandbox_operate import SandBoxHandlerForUpgrade
from plugins.DistributedStorage.Upgrade.params.params_config import ParamsConfig, DYNAMIC_CHECK_LIST


PARAMETER_VERIFY_ERROR = 33759491
PWD_VERIFY_ERROR = 33759566
NORMAL_CODE = 0


class DisableSandBoxStatusInf(StepBaseInterface, ABC):
    def __init__(self, project_id, pod_id, regionid_list=None, suit_id=None):
        super(DisableSandBoxStatusInf, self).__init__(project_id, pod_id, regionid_list)
        self.project_id = project_id
        self.pod_id = pod_id
        self.regionid_list = regionid_list
        self.region_id = regionid_list[0]
        self.suit_id = suit_id
        self.fs_args = ParamsGain(project_id, pod_id, regionid_list).get_args(suit_id)
        self.params_util = ParamUtil()
        self.passwd_error_code = 621026
        self.disable_sandbox_error = 626386

    def execute(self, project_id, pod_id, regionid_list=None, suit_id=None):
        try:
            self.procedure()
        except Exception as err:
            logger.error("Sandbox error:{}, details:{}".format(err, traceback.format_exc()))
            return Message(500, err)
        return Message()

    def rollback(self, project_id, pod_id, regionid_list=None, suit_id=None):
        """
        标准调用接口：执行回滚
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message()

    def retry(self, project_id, pod_id, regionid_list=None, suit_id=None):
        """
        标准调用接口：重试
        :return: Message类对象
        """
        self.update_fsm_cloud_params()

        logger.info("Obtain the fs_args parameters again")
        self.fs_args = ParamsGain(project_id, pod_id, regionid_list).get_args(suit_id)
        return self.execute(self.project_id, self.pod_id, self.regionid_list, self.suit_id)

    def update_fsm_cloud_params(self):
        logger.info("Update fsm cloud_params")
        params_cfg = ParamsConfig(self.project_id)
        fsm_ip_list = [self.fs_args.get("master_ip"), self.fs_args.get("slaver_ip")]
        dynamic_param_keys = [str(key).format(self.suit_id) for key in DYNAMIC_CHECK_LIST]
        fsm_node_infos = params_cfg.get_fsm_node_infos_for_one_step_upgrade(dynamic_param_keys, fsm_ip_list)
        if fsm_node_infos.get(f"FSM_{self.suit_id}_active_ip") == self.fs_args.get("master_ip"):
            pwd_dict = {
                f"FSM_{self.suit_id}_active_pwd": crypt.decrypt(fsm_node_infos.get(f"FSM_{self.suit_id}_active_pwd")),
                f"FSM_{self.suit_id}_active_root_pwd": crypt.decrypt(
                    fsm_node_infos.get(f"FSM_{self.suit_id}_active_root_pwd")
                ),
                f"FSM_{self.suit_id}_standby_pwd": crypt.decrypt(fsm_node_infos.get(f"FSM_{self.suit_id}_standby_pwd")),
                f"FSM_{self.suit_id}_standby_root_pwd": crypt.decrypt(
                    fsm_node_infos.get(f"FSM_{self.suit_id}_standby_root_pwd")
                )
            }
        else:
            pwd_dict = {
                f"FSM_{self.suit_id}_active_pwd": crypt.decrypt(fsm_node_infos.get(f"FSM_{self.suit_id}_standby_pwd")),
                f"FSM_{self.suit_id}_active_root_pwd": crypt.decrypt(
                    fsm_node_infos.get(f"FSM_{self.suit_id}_standby_root_pwd")
                ),
                f"FSM_{self.suit_id}_standby_pwd": crypt.decrypt(fsm_node_infos.get(f"FSM_{self.suit_id}_active_pwd")),
                f"FSM_{self.suit_id}_standby_root_pwd": crypt.decrypt(
                    fsm_node_infos.get(f"FSM_{self.suit_id}_active_root_pwd")
                )
            }
        self.update_fsm_pwd(pwd_dict)

    def update_fsm_pwd(self, pwd_dict: dict):
        logger.info("update fsm info")
        for key, value in pwd_dict.items():
            self.params_util.set_service_cloud_param(self.project_id, SERVICE_NAME, self.region_id, key, value)

    def procedure(self):
        # 813及之后版本，一跳升级，需关闭安全沙箱；
        sandbox_opr = SandBoxHandlerForUpgrade(self.fs_args)
        if not sandbox_opr.is_after_813:
            logger.info("Current Version:{}, no sandbox, pass".format(sandbox_opr.version))
            return

        logger.info("start to disable FSM sandbox")
        for ip_addr in sandbox_opr.fsm_node:
            self.exec_disable_sandbox(ip_addr, sandbox_opr)

        logger.info("Succeeded in closing the sandbox.")

    def exec_disable_sandbox(self, ip_addr, sandbox_opr: SandBoxHandlerForUpgrade):
        resp = sandbox_opr.opr.disable_sandbox_handle(sandbox_opr.request_body.get(ip_addr))
        logger.info("node:{}, details:{}".format(ip_addr, resp))
        result, data = resp.get('result'), resp.get('data')
        if result.get("code") != NORMAL_CODE:
            raise HCCIException(self.disable_sandbox_error, resp)
        for node in data:
            if str(node.get('code')) != str(NORMAL_CODE):
                if str(node.get('code')) in [str(PARAMETER_VERIFY_ERROR), str(PWD_VERIFY_ERROR)]:
                    raise HCCIException(self.passwd_error_code, ip_addr, resp)
                else:
                    raise HCCIException(self.disable_sandbox_error, resp)
