# -*- coding: UTF-8 -*-
import re
from resource.resource import MESSAGES_DICT
from cbb.frame.cli import cliUtil
from cbb.frame.context import contextUtil
from cbb.frame.base import baseUtil


ALARM_COMM = ['0xF00170014', '0xF00170017', '0xF00170018', '0xF00170019', '0xF0017001A', '0xF0050001', '0xF00CA000E',
              '0xF00CA000F', '0xF00CE0015', '0xF00CE002E', '0xF00CE0031', '0xF00CE0032', '0xF00CF0036', '0xF00CF005F',
              '0xF00CF0071', '0xF00CF0072', '0xF00CF0077', '0xF00CF0084', '0xF00D00014', '0xF00D00018', '0xF00D0001F',
              '0xF00D00022', '0xF00D00023', '0xF00D00026', '0xF00D00028', '0xF00D20014', '0xF00D20019', '0xF00D2001B',
              '0xF00D2001C', '0xF00D2001D', '0xF00D2001E', '0xF00D30014', '0xF00D30015', '0xF00D30016', '0xF00D30017',
              '0xF00EA0016', '0xF00EA0017', '0xF01320002', '0xF01320004', '0xF01320005', '0xF01320006', '0xF01320044',
              '0xF0170002', '0xF0170005', '0xF0C90006', '0xF0CE0001', '0xF0CE0005', '0xF0CE0007', '0xF0CE0008',
              '0xF0CE0009', '0xF0CE000A', '0xF0CF0005', '0xF0CF0006', '0xF0D20004', '0xF0D20005', '0xF0D30003']
ALARM_V6 = ['0xF00CF0076', '0xF00CF0079', '0xF00CF007A', '0xF00CF007B', '0xF00D00029']
ALARM_V5 = ['0xF00170015', '0xF00170016', '0xF0050002', '0xF0050003', '0xF00CE0014', '0xF00CE0035', '0xF00CF0014',
            '0xF00CF0017', '0xF00CF004A', '0xF00CF0063', '0xF00CF0068', '0xF00CF0069', '0xF00CF0073', '0xF00CF0078',
            '0xF00D0001E', '0xF0170004', '0xF0CE0004', '0xF0D30004']
ALARM_601SPH35 = ['0x000F00C90156', '0x100F00CF0034', '0x100F0C9000C', '0x100F0C90065', '0xF00C9013D', '0xF00C90150',
                  '0xF00CE002A', '0xF00CF0014', '0xF00CF0035', '0xF00CF0061', '0xF00CF0070', '0xF00CF0073',
                  '0xF00CF007F', '0xF00CF0082', '0xF00ED000F', '0xF0170004']
ALARM_610SPH27 = ['0x000F00C90156', '0x100F00CF0029', '0x100F00CF0034', '0x100F0C9000C', '0x100F0C90065',
                  '0xF00C9013D', '0xF00C90150', '0xF00CE002A', '0xF00CF0014', '0xF00CF0035', '0xF00CF0061',
                  '0xF00CF0070', '0xF00CF0073', '0xF00CF007F', '0xF00CF0088']
ALARM_612SPH30 = ['0x200F022E0011', '0xF00170015', '0xF00170016', '0xF00170021', '0xF00C90150', '0xF00C90156',
                  '0xF00C9015A', '0xF00C9015D', '0xF00C9015E', '0xF00CE002A', '0xF00CF0061', '0xF00CF0070',
                  '0xF00CF0078', '0xF00CF0082', '0xF00CF0088', '0xF00CF008B', '0xF00CF008C', '0xF00CF0091',
                  '0xF00CF0093', '0xF00CF0096', '0xF00CF0097', '0xF00CF0098', '0xF00D0002C', '0xF00D30018',
                  '0xF00ED000A', '0xF00ED000B', '0xF00ED000F', '0xF00ED0010', '0xF0170004']
ALARM_613SPH10 = ['0x100F00CF0034', '0x100F0C9000C', '0x100F0C90065', '0xF00170015', '0xF00170016', '0xF00170021',
                  '0xF00C9013D', '0xF00C90150', '0xF00C90156', '0xF00C9015A', '0xF00C9015D', '0xF00C9015E',
                  '0xF00CF0035', '0xF00CF0078', '0xF00CF007F', '0xF00CF0082', '0xF00CF0088', '0xF00CF008B',
                  '0xF00CF008C', '0xF00CF0091', '0xF00CF0093', '0xF00CF0096', '0xF00CF0097', '0xF00D0002C',
                  '0xF00D30018', '0xF00ED000A', '0xF00ED000B', '0xF00ED000F', '0xF00ED0010', '0xF0170004']
ALARM_615SPH8 = ['0x000F00C90156', '0xF00170015', '0xF00170016', '0xF00170021', '0xF00C9013D', '0xF00C90156',
                 '0xF00C90160', '0xF00CF0078', '0xF00CF007F', '0xF00CF0082', '0xF00CF0088', '0xF00CF008B',
                 '0xF00CF008C', '0xF00CF0091', '0xF00CF0093', '0xF00CF0096', '0xF00CF0097', '0xF00D0002C',
                 '0xF00D30018', '0xF00ED000A', '0xF00ED000B', '0xF00ED000F', '0xF00ED0010', '0xF0170004']
ALARM_V5R7C60SPH111 = []
ALARM_V5R7C60SPH330 = ['0xF00C9013D', '0xF00CF007B', '0xF00D00029', '0xF00ED000F']
ALARM_V5R7C70SPH210 = ['0xF00C9013D', '0xF00CF007B', '0xF00CF0089', '0xF00CF008E', '0xF00D00029', '0xF00ED0005']
ALARM_V5R7C71SPH130 = ['0xF00C9013D', '0xF00CF007B', '0xF00CF0089', '0xF00CF008B', '0xF00D00029', '0xF00D30018',
                       '0xF00ED000F']
ALARM_V5R7C73SPH110 = ['0xF00C9013D', '0xF00CF007B', '0xF00CF0089', '0xF00CF008B', '0xF00CF0091', '0xF00CF0093',
                       '0xF00D00029', '0xF00D30018', '0xF00ED000A', '0xF00ED000B']

PRODUCT_MODEL_H = [
    "OceanStor Dorado 8000 V6", "OceanStor Dorado 18000 V6", "OceanStor Dorado 6800 V6",
    "OceanStor Dorado 18500 V6", "OceanStor Dorado 18800 V6", "OceanStor Dorado 18800K V6",
    "OceanStor 6810", "OceanStor 18510", "OceanStor 18500K", "OceanStor 18810",
    "6800 V5", "6800F V5", "6800K V5", "6810 V5", "6810F V5", "18500 V5", "18500F V5", "18500K V5",
    "18510 V5", "18510F V5", "18800 V5", "18800F V5", "18800K V5", "18810 V5", "18810F V5",
]


def execute(data_dict):
    """
    :功能描述: 检查电源升级状态
    """

    check_item = CheckAlarmBeforePowerUpgrade(data_dict)
    result = check_item.execute()
    if result:
        return True, "", "\n".join(check_item.origin_info)
    return False, "\n".join(check_item.msg_list), "\n".join(check_item.origin_info)


class CheckAlarmBeforePowerUpgrade:
    def __init__(self, data_dict):
        self.data_dict = data_dict
        self.cli = contextUtil.getCli(data_dict)
        self.logger = contextUtil.getLogger(data_dict)
        self.lang = contextUtil.getLang(data_dict)
        self.dev = self.data_dict.get("dev")
        self.dev_type = str(self.dev.getDeviceType())
        self.origin_info = []
        self.msg_list = []

    def execute(self):
        alarm_blocklist = self.get_alarm_blocklist()
        self.origin_info.append(str(alarm_blocklist))
        if len(alarm_blocklist) == 0:
            return True
        if self.check_psu_target():
            return True
        cli_cmd = "show alarm|filterColumn include columnList=Sequence,ID"
        is_suc, cli_ret, err_msg = cliUtil.execCmdInCliMode(self.cli, cli_cmd, True, self.lang)
        alarm_dict = cliUtil.getHorizontalCliRet(cli_ret)
        alarm_msg = ""
        check_ret = True
        self.logger.info(str(alarm_dict))
        for alarm_info in alarm_dict:
            # 密码即将过期 || 密码已经过期
            if alarm_info.get("ID") == "0xF00CA000E" or alarm_info.get("ID") == "0xF00CA000F":
                cli_cmd = "show alarm sequence={}".format(alarm_info.get("Sequence"))
                is_suc, cli_ret, err_msg = cliUtil.execCmdInCliMode(self.cli, cli_cmd, True, self.lang)
                if "(admin)" in cli_ret:
                    check_ret = False
                    alarm_msg += "alarm ID: {}, Sequence:{}\n" \
                                            .format(alarm_info.get("ID"), alarm_info.get("Sequence"))
            elif alarm_info.get("ID") in alarm_blocklist:
                check_ret = False
                alarm_msg += "alarm ID: {}, Sequence:{}\n" \
                                        .format(alarm_info.get("ID"), alarm_info.get("Sequence"))
        if check_ret:
            return True
        self.msg_list.append(self.get_msg("power.patch.upgrade.alarm"))
        self.msg_list.append(alarm_msg)
        return False

    def get_alarm_blocklist(self):
        patch_version_dict = {'6.0.1': 'SPH35', '6.1.0': 'SPH27', '6.1.2': 'SPH30', '6.1.3': 'SPH10', '6.1.5': 'SPH8',
                              'V500R007C60SPC100': 'V500R007C60SPH111', 'V500R007C60SPC300': 'V500R007C60SPH330',
                              'V500R007C70SPC200': 'V500R007C70SPH210', 'V500R007C71SPC100': 'V500R007C71SPH130',
                              'V500R007C73SPC100': 'V500R007C73SPH110'}
        alarm_dict = {'6.0.1': ALARM_COMM + ALARM_V6 + ALARM_601SPH35,
                      '6.1.0': ALARM_COMM + ALARM_V6 + ALARM_610SPH27,
                      '6.1.2': ALARM_COMM + ALARM_V6 + ALARM_612SPH30,
                      '6.1.3': ALARM_COMM + ALARM_V6 + ALARM_613SPH10,
                      '6.1.5': ALARM_COMM + ALARM_V6 + ALARM_615SPH8,
                      'V500R007C60SPC100': ALARM_COMM + ALARM_V5 + ALARM_V5R7C60SPH111,
                      'V500R007C60SPC300': ALARM_COMM + ALARM_V5 + ALARM_V5R7C60SPH330,
                      'V500R007C70SPC200': ALARM_COMM + ALARM_V5 + ALARM_V5R7C70SPH210,
                      'V500R007C71SPC100': ALARM_COMM + ALARM_V5 + ALARM_V5R7C71SPH130,
                      'V500R007C73SPC100': ALARM_COMM + ALARM_V5 + ALARM_V5R7C73SPH110}
        _, software_version, hotpatch_version, _ = cliUtil.get_system_version_with_ret(self.cli, self.lang)
        pkgpatch_version = self.data_dict.get("pkgVersion")
        log_info = "software version: {}, hotpatch version: {}, pkgpatch version: {}" \
                   .format(software_version, hotpatch_version, pkgpatch_version)
        self.origin_info.append(log_info)
        if software_version not in patch_version_dict: # 非目标版本
            return []
        if not self.check_patch_version(hotpatch_version, pkgpatch_version, patch_version_dict.get(software_version)):
            return []
        
        return alarm_dict.get(software_version)

    # 检查存在psu_model为PAC2000S12-BG，且psu_verdc != 121/124的电源
    def check_psu_target(self):
        _, software_ver, hotpatch_ver, _ = cliUtil.get_system_version_with_ret(self.cli, self.lang)
        cli_cmd = "show power_supply|filterColumn include columnList=ID,Version,Model,Serial\sNumber"
        _, cli_ret, _ = cliUtil.execCmdInCliMode(self.cli, cli_cmd, True, self.lang)
        psu_list = cliUtil.getHorizontalCliRet(cli_ret)
        for psu_info in psu_list:
            psu_id = psu_info.get("ID", "")
            psu_model = psu_info.get("Model", "")
            psu_verdc = psu_info.get("Version", "")
            if "CTE" in psu_id and self.dev_type in PRODUCT_MODEL_H: # 高端控制框PSU不识别风险电源
                continue
            # 存在需要升级psu，psu_model为PAC2000S12-BG，且psu_verdc = 111/113/115/119
            if psu_model == "PAC2000S12-BG":
                if software_ver in ['6.0.1', 'V500R007C60SPC100', 'V500R007C60SPC300']:
                    return False
                if psu_verdc != "" and psu_verdc.split(".")[0] in ['111', '113', '115', '119']:
                    return False
        return True # 不存在需要升级psu

    def check_patch_version(self, cur_ver, pkg_ver, target_ver):
        if compare_patch_version(pkg_ver, target_ver) >= 0:
            if compare_patch_version(cur_ver, target_ver) < 0:
                return True
        return False

    def get_msg(self, msg_key):
        return baseUtil.getPyResource(self.lang, msg_key, "", resource=MESSAGES_DICT)


def compare_patch_version(version1, version2):
    sph_ver_1 = format_patch_version(version1)
    sph_ver_2 = format_patch_version(version2)
    if sph_ver_1 == sph_ver_2:
        return 0
    return 1 if sph_ver_1 > sph_ver_2 else -1


def format_patch_version(version):
    find_versions = re.findall(r"SPH(\d+)", version)
    sph_ver = find_versions[0] if find_versions else "0"
    return "SPH{}".format(sph_ver.zfill(5))
