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

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


def open_file_util(file_name, mode='r', encoding=None, **kwargs):
    if mode in ['r', 'rt', 'tr'] and encoding is None:
        with open(file_name, 'rb') as f:
            context = f.read()
            encoding = get_encoding_type(context, encoding)
    return open(file_name, mode=mode, encoding=encoding, **kwargs)


def get_encoding_type(context, encoding):
    for encoding_item in ['UTF-8', 'GBK', 'ISO-8859-1']:
        try:
            context.decode(encoding=encoding_item)
        except UnicodeDecodeError as e:
            logger.error("decode error:{}".format(e))
            continue
        encoding = encoding_item
        break
    return encoding


class DoCheckTenantFBSlot(TestCase):
    def __init__(self, project_id, pod_id):
        self.script_dir = "/home/pkg/precheck/scripts/"
        self.local_dir = str(pathlib.Path(__file__ + '/../').resolve()/'shells/')
        self.rc_file = 'public_rcs'
        self.script_file = 'check_disk_slot_separate.sh'
        self.db = BaseOps()
        self.project_id = project_id
        self.pod_id = pod_id
        self.check_type = 'check_slot'

    def create_check_script(self, script_src_file, script_file, **kwargs):
        script_dst_file = self.script_dir + script_file
        script_dst_dir_bak = self.script_dir + "bak/"
        script_dst_file_bak = script_dst_dir_bak + script_file
        check_type = ''
        timestamp = ''
        with open_file_util(script_src_file, 'r') as s:
            content = s.read()
        for item in kwargs.items():
            pattern = re.compile(item[0] + '=.*')
            repl = '%s=%s' % (item[0], item[1])
            content = re.sub(pattern, repl, content)
            if item[0] == 'TIMESTAMP':
                timestamp = item[1]
            if item[0] == 'CHECKTYPE':
                check_type = item[1]
        suffix = '_' + check_type + '_' + timestamp
        logger.info('Parsed params: %s' % kwargs)
        content = content.replace('\r', '')
        with open_file_util(script_dst_file, 'w', encoding='utf-8') as d:
            d.write(content)

        if not os.path.exists(script_dst_dir_bak):
            os.mkdir(script_dst_dir_bak)
        with open_file_util(script_dst_file_bak + suffix, 'w', encoding='utf-8') as b:
            b.write(content)
        logger.info('Successfully create checking script for %s, timestamp: %s, check type: %s' %
                    (script_file, timestamp, check_type))

    def procedure(self):
        """检查管理节点、云服务节点的CPU"""
        ssh_util = Ssh()
        bmc_ip_list = []
        timestamp = str(int(time.time()))

        nodes_info = self.db.get_install_os_list_info(self.pod_id)
        disk_slots = nodes_info[0].get('storagepool_slot')
        script_src_file = self.local_dir + self.script_file
        self.create_check_script(script_src_file, self.script_file,
                                 TIMESTAMP=timestamp,
                                 CHECKTYPE=self.check_type,
                                 DISKSLOTS=disk_slots)

        for node in nodes_info:
            bmc_ip = node.get('bmc_ip')
            manage_ip = node.get('manageIp')
            user_info_list = node.get('creuser').split(',')
            root_passwd = user_info_list[1]
            username = user_info_list[2]
            user_passwd = user_info_list[3]
            ssh_util.put_file(manage_ip, username, user_passwd, self.script_dir + self.rc_file,
                              '/tmp')
            ssh_util.put_file(manage_ip, username, user_passwd, self.script_dir + self.script_file,
                              '/tmp')
            ssh_client = Ssh.ssh_create_client(manage_ip, username, user_passwd)
            Ssh.ssh_send_command(ssh_client, 'LANG=C', '$', 2)
            Ssh.ssh_send_command(ssh_client, 'su', 'assword', 10)
            Ssh.ssh_send_command(ssh_client, root_passwd, '#', 10)
            Ssh.ssh_send_command(ssh_client, 'cd /tmp', '#', 10)
            Ssh.ssh_send_command(ssh_client, 'bash %s' % self.rc_file, '#', 30)
            Ssh.ssh_send_command(ssh_client, 'bash %s' % self.script_file, 'Successfully', 30)
            Ssh.ssh_close(ssh_client)
            bmc_ip_list.append(bmc_ip)

        common_libs.check_all_result(bmc_ip_list, self.check_type, timestamp)


class CheckTenantFBSlot(StepBaseInterface):
    def __init__(self, project_id, pod_id):
        super(CheckTenantFBSlot, self).__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.implement = DoCheckTenantFBSlot(project_id, pod_id)

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

    def execute(self, project_id, pod_id):
        try:
            self.implement.procedure()
        except HCCIException as e1:
            logger.error("TenantFB separate slot check error:{}".format(traceback.format_exc()))
            return Message(500, e1)
        except Exception as e2:
            logger.error("TenantFB separate slot check error:{}".format(traceback.format_exc()))
            return Message(500, HCCIException('113999', 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:
        """
        pass
