#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import secrets
import utils.common.log as logger
from plugins.DistributedStorage.logic.deploy_operate import DeployOperate
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant
from plugins.DistributedStorage.Replication.scripts.common_utils.rest_constant import RestConstant
from plugins.DistributedStorage.Replication.scripts.common_utils.rest_response import RestResponse


class RestOperate(DeployOperate):
    def __init__(self, fsm_ip):
        fs_info = dict()
        fs_info["float_ip"] = fsm_ip
        super(RestOperate, self).__init__(fs_info)

    def query_dsware_client(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.QUERY_DSWARE_CLIENT

        res = self.rest_client.normal_request(url, 'get')
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query dsware client. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_manage_cluster(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.QUERY_MANAGE_CLUSTER

        res = self.rest_client.normal_request(url, 'get')
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query manage cluster. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_storage_pool(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.QUERY_STORAGE_POOL

        res = self.rest_client.normal_request(url, 'get')
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query storage pool. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_dsware_client(self, node_ip_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_CLIENT
        server_list = [{"nodeMgrIp": x, "nodeType": 0} for x in node_ip_list]
        client_data = {"servers": server_list}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create dsware client. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_control_cluster(self, cluster_medias_str):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        cluster_name = "cluster" + str(secrets.SystemRandom().choice(list(range(1, 10))))
        node_ip_str, medias_str = cluster_medias_str
        client_data = {
                        "clusterName": cluster_name,
                        "nodeIps": node_ip_str,
                        "serviceType": "dr",
                        "op": "drCmd",
                        "subOp": "createControlCluster",
                        "type": "CLUSTER",
                        "serverMediaConfigBody": medias_str,
                        "serverMediaConfigHead": "mediaTypeKey:mediaType,mediaTypeValue:physicalVolume,section:GLOBAL"}
        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create dsware client. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_control_cluster(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL

        client_data = {
                      "op": "drCmd",
                      "serviceType": "dr",
                      "subOp": "queryControlCluster"}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query control cluster. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_replication_cluster(self, ip_list, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        ip_str = ','.join(ip_list)
        client_data = {
                      "type": "CLUSTER",
                      "subOp": "createReplicateCluster",
                      "serviceType": "dr",
                      "nodeIps": ip_str,
                      "controlClusterId": ctl_cluster_id}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create replication cluster. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_rep_cls_psk(self, ctl_cluster_id, label, psk):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "PSK Label": label,
                      "PSK": psk,
                      "controlClusterId": ctl_cluster_id,
                      "op": "drCmd",
                      "serviceType": "dr",
                      "subOp": "CreateRepClsPSK",
                      "type": "CLUSTER"}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create replication ClsPSK. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_ip_pool(self, create_ip_pool_params, nick_name='rep0,rep1'):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        if not nick_name:
            client_data = {
                      "controlClusterId": create_ip_pool_params.get('control_cluster_id'),
                      "op": "drCmd",
                      "subOp": "CreateIpPool",
                      "serviceType": "dr",
                      "type": "IP_POOL",
                      "ipPoolName": create_ip_pool_params.get('ip_pool_name'),
                      "ipPoolPort": create_ip_pool_params.get('ip_pool_port'),
                      "netMask": create_ip_pool_params.get('net_mask0'),
                      "nodeInfo": create_ip_pool_params.get('node_addr_info')}
        else:
            client_data = {
                      "controlClusterId": create_ip_pool_params.get('control_cluster_id'),
                      "op": "drCmd",
                      "subOp": "CreateIpPool",
                      "serviceType": "dr",
                      "type": "IP_POOL",
                      "ipPoolName": create_ip_pool_params.get('ip_pool_name'),
                      "ipPoolPort": "12100",
                      "netMask": create_ip_pool_params.get('net_mask0'),
                      "nicName": nick_name,
                      "nodeInfo": create_ip_pool_params.get('node_addr_info')}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create IP pool. Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def add_ip_pool(self, add_ip_pool_params, ip_pool_id='1'):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + \
              RestConstant.DR_REST_URL
        client_data = {
            "op": "drCmd",
            "subOp": "expandIpPool",
            "name": "expandIpPool",
            "serviceType": "dr",
            "type": "IP_POOL",
            "controlClusterId": add_ip_pool_params.get('ctl_cluster_id'),
            "ipPoolId": ip_pool_id,
            "netMask": add_ip_pool_params.get('netmask'),
            "nicName": add_ip_pool_params.get('rep_nick_name'),
            "nodeInfo": add_ip_pool_params.get('node_addr_info')}
        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to add IP pool. Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_ip_pool(self, ctl_cluster_id, pool_id='0', count='10'):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + \
              RestConstant.DR_REST_URL
        client_data = {
            "controlClusterId": ctl_cluster_id,
            "op": "drCmd",
            "subOp": "BatchQueryIpPool",
            "serviceType": "dr",
            "type": "IP_POOL",
            "id": pool_id,
            "count": count}
        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query IP pool. Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_remote_device(self, remote_device_params):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "op": "drCmd",
                      "subOp": "CreateRemoteDevice",
                      "serviceType": "dr",
                      "type": "REMOTE_DEVICE",
                      "controlClusterId": remote_device_params.get('ctl_cluster_id'),
                      "localIpPoolId": remote_device_params.get('local_ip_pool_id'),
                      "remoteIpPoolId": remote_device_params.get('remote_ip_pool_id'),
                      "initLocalIp": remote_device_params.get('initial_local_ip'),
                      "initRemoteIp": remote_device_params.get('initial_remote_ip'),
                      "remote PSK Label": remote_device_params.get('psk_label'),
                      "remote PSK": remote_device_params.get('psk_passwd')}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create remote device. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_hyper_domain(self, ctl_cluster_id, domain_name, domain_type, remote_device_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        remote_dev_id_str = "\"devId\":\"%s\"" % remote_device_id
        client_data = {
                      "serviceType": "dr",
                      "subOp": "CreateHyperMetroDomain",
                      "name": domain_name,
                      "remoteDeviceId": remote_dev_id_str,
                      "controlClusterId": ctl_cluster_id,
                      "domainType": domain_type}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create hyper domain. Detail:[result:%s,code:%s]%s' % (status_code, error_code,
                                                                                       error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_quorum_server(self, quorum_server_name, server_ip_port, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "name": quorum_server_name,
                      "quorumServerIp": server_ip_port,
                      "subOp": "CreateQuorumServer",
                      "serviceType": "dr",
                      "controlClusterId": ctl_cluster_id}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create quorum server. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def create_associate(self, ctl_cluster_id, quorum_server_id, domain_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "serviceType": "dr",
                      "subOp": "CreateAssociate",
                      "controlClusterId": ctl_cluster_id,
                      "associateObjID": quorum_server_id,
                      "associateObjType": "QuorumServer",
                      "hyperMetroDomainId": domain_id,
                      "domainType": "HC_DOMAIN_TYPE_AA"}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to create associate. Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_ip_pool_info(self, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "controlClusterId": ctl_cluster_id,
                      "op": "drCmd",
                      "subOp": "BatchQueryIpPool",
                      "serviceType": "dr",
                      "type": "IP_POOL",
                      "id": "0",
                      "count": "100"}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query ip pool info. Detail:[result:%s,code:%s]%s' % (status_code, error_code,
                                                                                      error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_remote_device(self, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "op": "drCmd",
                      "subOp": "BatchQueryRemoteDevice",
                      "type": "REMOTE_DEVICE",
                      "controlClusterId": ctl_cluster_id,
                      "id": "0",
                      "count": "100",
                      "serviceType": "dr"}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query remote device info. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_rep_cls_psk(self, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "controlClusterId": ctl_cluster_id,
                      "op": "drCmd",
                      "serviceType": "dr",
                      "subOp": "QueryRepClsPSK",
                      "name": [
                                 "CLUSTER"
                               ]}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query replication ClsPSK info. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_hyper_metro_domain(self, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "controlClusterId": ctl_cluster_id,
                      "serviceType": "dr",
                      "subOp": "BatchQueryHyperMetroDomain",
                      "count": 2,
                      "id": 0}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query hyper metro domain info. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def query_quorum_server(self, ctl_cluster_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "controlClusterId": ctl_cluster_id,
                      "id": "0",
                      "subOp": "BatchQueryQuorumServer",
                      "serviceType": "dr",
                      "count": 10}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to query quorum server info. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result

    def delete_quorum_server(self, ctl_cluster_id, server_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + RestConstant.DR_REST_URL
        client_data = {
                      "id": server_id,
                      "controlClusterId": ctl_cluster_id,
                      "type": "REP_CPS",
                      "subOp": "DeleteQuorumServer",
                      "serviceType": "dr"}

        res = self.rest_client.normal_request(url, 'post', client_data)
        result = RestResponse(res)
        status_code, error_code, error_des = result.get_query_code()
        if status_code != 0:
            err_msg = 'Failed to delete quorum server info. ' \
                      'Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise Exception(err_msg)
        return result
