# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import traceback
import utils.common.log as logger
from utils.common.ssh_util import Ssh as ssh
from utils.common.exception import HCCIException
from utils.common.fic_base import StepBaseInterface
from utils.common.message import Message
from utils.DBAdapter.DBConnector import BaseOps
from plugins.DistributedStorage.utils.common.deploy_constant import ComponentName
from plugins.DistributedStorage.logic.install_operate import InstallOperate
from plugins.DistributedStorage.Deploy.scripts.PreCheck.common.device_operate import PreCheckPublicOperate


class FirstLoginStatus:
    FINISH = "1"
    NOT_INIT = "not_init"


class ConfigServiceNodeFirstLoginIntf(StepBaseInterface):
    """
    根据版本配置：fsadmin用户首次登录必须修改密码；普通用户密码有效期90天，root密码永不过期
    涉及场景：底座部署
            扩AZ新建
            扩AZ复用
            新增业务存储 - 新建存储池、新增存储节点、新增复制集群、IP/FC SAN扩分布式
            扩可选云服务 - 新增复制集群
    """
    def __init__(self, project_id, pod_id):
        super(ConfigServiceNodeFirstLoginIntf, self).__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.pre_check_opr = PreCheckPublicOperate(self.project_id, self.pod_id)
        self.data_base = BaseOps()
        self.error_code = 626298
        self.server_key = "ServiceNodesFirstLoginStatus"
        self.host_list = self.pre_check_opr.get_bmc_info()
        self.first_login_status = self.data_base.get_value_from_cloudparam(
            self.project_id, ComponentName.DEPLOY, self.server_key)

    @classmethod
    def handler(cls, cmd: str, host_info: dict, timeout=20):
        manage_ip = host_info.get("manageIp")
        _, root_pwd, user, user_passwd = host_info.get("creuser").split(',')
        try:
            ssh_client = InstallOperate.create_ssh_root_client(manage_ip, user, user_passwd, root_pwd)
        except Exception as err:
            return False, manage_ip, "error:{}, details:{}".format(err, traceback.format_exc())

        cmd = cmd.format(user)
        try:
            ssh.ssh_send_command(ssh_client, cmd, '#', timeout)
        except Exception as err:
            return False, manage_ip, "error:{}, details:{}".format(err, traceback.format_exc())
        return True, manage_ip, ""

    @classmethod
    def get_retry_host_list(cls, first_login_status: str, host_list: list):
        new_host_list = []
        for node_ip in first_login_status.split(","):
            for host_info in host_list:
                if host_info.get("manageIp") == node_ip:
                    new_host_list.append(host_info)
                    break
        return new_host_list

    def procedure(self):
        logger.info('Start to configure first login.')

        if self.first_login_status == FirstLoginStatus.FINISH:
            logger.info("first_login_status:{}, "
                        "No node needs to be configured, pass.".format(self.first_login_status))
            return
        elif self.first_login_status == FirstLoginStatus.NOT_INIT:
            logger.info("first_login_status:{}, "
                        "Configuring First Login for the first time.".format(self.first_login_status))
            self.config_first_login(self.host_list)
        else:
            logger.info("Node that fails to be set for the first time:{}".format(self.first_login_status))
            new_host_list = self.get_retry_host_list(self.first_login_status, self.host_list)
            self.config_first_login(new_host_list)

        logger.info("The configuration is complete.")

    def config_first_login(self, host_list):
        cmd = 'chage -M 90 {};chage -M 90 fsadmin;chage -d 0 fsadmin'
        res = InstallOperate.multi_thread_exec_cmd(host_list, self.handler, cmd, timeout=20)
        if res:
            err_msg = "Failed to configuring the First Login, details:{}".format(res)
            logger.error(err_msg)
            failed_node_ip = ",".join(res.keys())
            self.update_param(failed_node_ip)
            raise HCCIException(self.error_code, "Failed nodes:{}, details:{}".format(failed_node_ip, err_msg))
        else:
            self.update_param(FirstLoginStatus.FINISH)

    def update_param(self, param_value):
        self.data_base.update_cloud_param(
            ComponentName.DEPLOY,
            self.server_key,
            self.project_id,
            self.pod_id,
            {"param_value": param_value}
        )

    def execute(self, project_id, pod_id):
        """
        标准调用接口：执行
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        try:
            self.procedure()
        except HCCIException as err:
            return Message(500, err)
        except Exception as err:
            logger.error("Failed to configure the First Login of the Service Node, "
                         "details：{}".format(traceback.format_exc()))
            return Message(500, HCCIException(self.error_code, str(err)))
        return Message(200)

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

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

    def check(self, project_id, pod_id):
        """
        标准调用接口
        :return: Message类对象
        """
        return Message(200)
