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

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 utils.business.project_condition_utils import get_project_condition_boolean
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc


class DoCheckNic(TestCase):
    QUERY_ETH_CMD = "ip addr | grep '^[0-9]' |awk -F':' '{print $2}'|grep -v 'lo'"
    HANDLER = r'echo -n "$eth," && ethtool $eth 2>/dev/null|grep -E "Speed: |Link detected:"|tr -d "\t"|tr "\n" "," '
    CHECK_CMD = fr"""for eth in `{QUERY_ETH_CMD}`; do {HANDLER}; echo ""; done"""

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

    @staticmethod
    def check_nic_info(bmc_ip_result, nic_num, nic_speed, connect_check=True):
        ret = False
        if bmc_ip_result["result"] == '1':
            return ret
        if nic_num == 0:
            return ret
        nic_num = float(nic_num)
        nic_speed = float(nic_speed)
        nic_num_yes = 0
        ret_lst = bmc_ip_result["stdout"].split("\n")
        if connect_check:
            nic_num_yes, ret = DoCheckNic.nic_connect_check(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

    @staticmethod
    def nic_connect_check(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
            match_ret = pattern.match(nic_info)
            if not match_ret:
                continue
            nic_speed_yes = int(match_ret.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 procedure(self):
        bmc_info_lists = self.db.get_install_os_list_info(self.pod_id)
        nic_speed_10ge = 10*1000
        nic_speed_ge = 1000
        bmc_ip_list = [bmc_info["bmc_ip"] for bmc_info in bmc_info_lists]
        result = self.cmd_exe.run(bmc_ip_list, self.CHECK_CMD)
        logger.info("Exec cmd: %s, result: %s" % (self.CHECK_CMD, result))
        for bmc_info in bmc_info_lists:
            bmc_ip = bmc_info['bmc_ip']
            logger.info("bmc_ip:%s Nic check" % bmc_ip)
            mgmt_plane_set = set(bmc_info.get('management_plane').split(','))
            storage_plane_set = set(bmc_info.get('storage_plane').split(','))
            if mgmt_plane_set.difference(storage_plane_set):
                nic_num_10ge = 2
                nic_num_ge = 2
            else:
                nic_num_10ge = 2
                nic_num_ge = 0

            if get_project_condition_boolean(
                    self.project_id, "(CSHAStorage_TFB|CSDRStorage_TFB)&!DRStorage_TFB_Sep"):
                nic_num_10ge = nic_num_10ge + 2

            check_result = self.check_nic_info(result[bmc_ip], nic_num_10ge + nic_num_ge, nic_speed_10ge, True)
            check_result = check_result or (
                    self.check_nic_info(result[bmc_ip], nic_num_10ge, nic_speed_10ge, True) and
                    self.check_nic_info(result[bmc_ip], nic_num_ge, nic_speed_ge, True))

            if not check_result:
                logger.error("Nic check faild!")
                raise HCCIException("625303", bmc_info['bmc_ip'], nic_num_10ge + nic_num_ge)
            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:
            logger.error("nic check error:{}".format(traceback.format_exc()))
            return Message(500, e1)
        except Exception as e2:
            logger.error("nic check error:{}".format(traceback.format_exc()))
            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)
