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

import utils.common.log as logger
from utils.DBAdapter.DBConnector import BaseOps
from utils.common.exception import HCCIException
from utils.common.fic_base import StepBaseInterface
from utils.common.fic_base import TestCase
from utils.common.message import Message
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc

logger.init("FusionStorageBlockReplication")


class DoCheckNic(TestCase):
    def __init__(self, project_id, pod_id):
        self.project_id = project_id
        self.pod_id = pod_id
        self.cmd_exe = BMCCmdExc()
        self.db = BaseOps()

    @staticmethod
    def connect_check_handle(nic_num, nic_num_yes, nic_speed, ret, ret_lst):
        pattern = re.compile(r'.*? (\d+)Mb/s')
        for nic_info in ret_lst:
            if "yes" not in nic_info:
                continue
            m = pattern.match(nic_info)
            nic_speed_yes = int(m.group(1))
            if nic_speed_yes == nic_speed:
                nic_num_yes += 1
                if nic_num_yes == nic_num:
                    ret = True
                    break
        return nic_num_yes, ret

    def check_nic_info(self, bmc_ip_result, nic_num, nic_speed, connect_check=True):
        ret = False
        if bmc_ip_result["result"] == '1':
            return ret
        nic_speed = float(nic_speed)
        nic_num_yes = 0
        ret_lst = bmc_ip_result["stdout"].split("\n")
        if connect_check:
            nic_num_yes, ret = self.connect_check_handle(nic_num, nic_num_yes, nic_speed, ret, ret_lst)
        else:
            for nic_info in ret_lst:
                if "Speed" not in nic_info:
                    continue
                nic_num_yes += 1
                if nic_num_yes == nic_num:
                    ret = True
                    break

        if nic_num_yes < nic_num:
            ret = False
        return ret

    def procedure(self):
        bmc_info_lists = self.db.get_install_os_list_info(self.pod_id, "rep")
        nic_speed_10ge = 10 * 1000
        nic_speed_ge = 1000
        bmc_ip_list = [bmc_info["bmc_ip"] for bmc_info in bmc_info_lists]
        query_eth_cmd = "ip addr | grep '^[0-9]' |awk -F':' '{print $2}'|grep -v 'lo'"
        handle_cmd = 'echo -n "$eth," && ' \
                     'ethtool $eth 2>/dev/null|grep -E "Speed: |Link detected:"|tr -d "\t"|tr "\n" "," '
        cmd = fr"""for eth in `{query_eth_cmd}`; do {handle_cmd}; echo ""; done"""
        result = self.cmd_exe.run(bmc_ip_list, cmd)
        for bmc_info in bmc_info_lists:
            bmc_ip = bmc_info['bmc_ip']
            logger.info("bmc_ip:%s Nic check" % bmc_ip)
            if len(bmc_info.get('management_plane').split(',')) == 2:
                nic_num = 6
                check_result = self.check_nic_info(result[bmc_ip], nic_num, nic_speed_10ge, True)
                check_result = check_result or (
                        self.check_nic_info(result[bmc_ip], 2, nic_speed_ge, True) and
                        self.check_nic_info(result[bmc_ip], 4, nic_speed_10ge, True))
            else:
                nic_num = 4
                check_result = self.check_nic_info(result[bmc_ip], nic_num, nic_speed_10ge, True)
            if not check_result:
                logger.info("Nic check faild!")
                raise HCCIException("627203", bmc_info['bmc_ip'], nic_num)
            logger.info("Nic check success!")


class CheckNic(StepBaseInterface):
    def __init__(self, project_id, pod_id):
        super(CheckNic, self).__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.implement = DoCheckNic(project_id, pod_id)

    def pre_check(self, project_id, pod_id):
        """
        插件内部接口：执行安装前的资源预检查，该接口由execute接口调用，工具框架不会直接调用此接口。
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message(200)

    def execute(self, project_id, pod_id):
        try:
            self.implement.procedure()
        except HCCIException as e1:
            return Message(500, e1)
        except Exception as e2:
            return Message(500, HCCIException('625301', str(e2)))
        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):
        """
        标准调用接口：重试
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message(200)
