# -*- coding: utf-8 -*-
# @Time : 2022/7/15 17:01
# @Author : wangyinghao
# @Site : 
# @File : api_interfaces_case_view.py
# @Software: PyCharm
from datetime import datetime
from django.views.generic import View
import json
import re
from django.forms import model_to_dict
from automated_main.utils.http_format import response_success, response_failed
from automated_main.exception.my_exception import MyException
from automated_main.models.api_automation.api_interfaces_case import ApiInterfacesCase, ApiInterfacesParameterData
from automated_main.form.api_interfaces_case import ApiInterfacesCaseForm
from automated_main.utils.api_utils import RegularMatch, InterfaceRequest, ExtractParameters
from automated_main.models.api_automation.api_environment import APIEnvironment
from automated_main.models.api_automation.api_database import APIDatabase
from automated_main.utils.handle_db import HandleDB
from automated_main.models.api_automation.api_interfaces_case import ApiInterfacesParameterExtraction

import logging

logger = logging.getLogger('django')


class ApiInterfacesCaseView(View):

    def put(self, request, *args, **kwargs):
        """
        创建接口测试用例
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        body = request.body
        if not body:
            return response_success()
        data = json.loads(body)
        form = ApiInterfacesCaseForm(data)

        if form.is_valid():
            api_interfaces_case = ApiInterfacesCase.objects.create(**form.cleaned_data)
            api_test_case_id = api_interfaces_case.id

            for api_parameter_extraction in data['api_parameter_extraction']:

                if api_parameter_extraction['api_key_variable'] == "":
                    pass

                elif api_parameter_extraction['api_key_variable'] != "":
                    if ApiInterfacesParameterExtraction.objects.filter(
                            api_key_variable=api_parameter_extraction['api_key_variable']).count() > 0:
                        api_test_case_id.delete()
                        return response_failed("30000", "变量名称重复,请重新填写")
                    else:
                        ApiInterfacesParameterExtraction.objects.create(api_test_case_id=api_test_case_id,
                                                                        api_variable_results=api_parameter_extraction[
                                                                            'api_variable_results'],
                                                                        api_value_variable=api_parameter_extraction[
                                                                            'api_value_variable'],
                                                                        api_key_variable=api_parameter_extraction[
                                                                            'api_key_variable'])
            for api_parameter in data['api_parameter']:
                ApiInterfacesParameterData.objects.create(api_test_case_id=api_test_case_id,
                                                          api_parameter_name=api_parameter['api_parameter_name'],
                                                          api_must_parameter=api_parameter['api_must_parameter'],
                                                          api_parameter_value=api_parameter['api_parameter_value'],
                                                          api_field_describe=api_parameter['api_field_describe'])

            return response_success("创建API测试用例成功")

        else:

            raise MyException()

    def get(self, request, api_interfaces_case_id, *args, **kwargs):
        """
        获取单独接口测试用例
        :param request:
        :param args:
        :param api_interfaces_case_id:
        :param kwargs:
        :return:
        """

        api_test_case = ApiInterfacesCase.objects.filter(id=api_interfaces_case_id).first()
        api_parameter_extractions = ApiInterfacesParameterExtraction.objects.filter(
            api_test_case_id=api_interfaces_case_id)
        api_parameter_extraction_list = []

        api_parameter_data_list = []
        api_parameter_data = ApiInterfacesParameterData.objects.filter(api_test_case_id=api_interfaces_case_id)
        if api_parameter_data.count() > 0:
            for api_parameter in api_parameter_data:
                api_parameter_dict = {
                    "api_must_parameter": api_parameter.api_must_parameter,
                    "api_parameter_name": api_parameter.api_parameter_name,
                    "api_parameter_value": api_parameter.api_parameter_value,
                    "api_field_describe": api_parameter.api_field_describe
                }
                api_parameter_data_list.append(api_parameter_dict)

        if api_parameter_extractions.count() > 0:
            for api_parameter_extraction in api_parameter_extractions:
                api_parameter_extraction_dict = {
                    "api_variable_results": api_parameter_extraction.api_variable_results,
                    "api_value_variable": api_parameter_extraction.api_value_variable,
                    "api_key_variable": api_parameter_extraction.api_key_variable

                }
                api_parameter_extraction_list.append(api_parameter_extraction_dict)

        else:
            api_parameter_extraction_dict = {

                "api_variable_results": "",
                "api_value_variable": "",
                "api_key_variable": ""

            }
            api_parameter_extraction_list.append(api_parameter_extraction_dict)

        if api_test_case is None:
            return response_success()
        else:
            api_test_case_dict = model_to_dict(api_test_case)
            api_test_case_dict['api_parameter_extraction'] = api_parameter_extraction_list
            api_test_case_dict['api_parameter'] = api_parameter_data_list

            return response_success(api_test_case_dict)

    def post(self, request, api_interfaces_case_id, *args, **kwargs):
        """
        编辑API测试用例
        :param request:
        :param args:
        :param api_interfaces_case_id:
        :param kwargs:
        :return:
        """

        api_test_case = ApiInterfacesCase.objects.filter(id=api_interfaces_case_id).first()
        if api_test_case is None:
            return response_success()
        body = request.body
        if not body:
            return response_success()

        data = json.loads(body)
        form = ApiInterfacesCaseForm(data)
        if form.is_valid():
            if ApiInterfacesParameterExtraction.objects.filter(api_test_case_id=api_interfaces_case_id).count() > 0:
                ApiInterfacesParameterExtraction.objects.delete()

                for api_parameter_extraction in data['api_parameter_extraction']:
                    if api_parameter_extraction['api_key_variable'] == "":
                        pass
                    elif ApiInterfacesParameterExtraction.objects.filter(
                            api_key_variable=api_parameter_extraction['api_key_variable']).count() > 0:
                        return response_failed("30000", "变量名称重复,请重新填写")
                    else:
                        ApiInterfacesParameterExtraction.objects.create(api_test_case_id=api_interfaces_case_id,
                                                                        api_variable_results=api_parameter_extraction[
                                                                            'api_variable_results'],
                                                                        api_value_variable=api_parameter_extraction[
                                                                            'api_value_variable'],
                                                                        api_key_variable=api_parameter_extraction[
                                                                            'api_key_variable'])

            else:
                logger.info("自定义变量表中 无 该 case_id")

                for api_parameter_extraction in data['api_parameter_extraction']:
                    if api_parameter_extraction['api_key_variable'] == "":
                        logger.info("api_key_variable是空")
                        pass

                    elif api_parameter_extraction['api_key_variable'] != "":
                        if ApiInterfacesParameterExtraction.objects.filter(
                                api_key_variable=api_parameter_extraction['api_key_variable']).count() > 0:
                            return response_failed("30000", "变量名称重复,请重新填写")
                        else:
                            ApiInterfacesParameterExtraction.objects.create(api_test_case_id=api_interfaces_case_id,
                                                                            api_variable_results=
                                                                            api_parameter_extraction[
                                                                                'api_variable_results'],
                                                                            api_value_variable=api_parameter_extraction[
                                                                                'api_value_variable'],
                                                                            api_key_variable=api_parameter_extraction[
                                                                                'api_key_variable'])
            if ApiInterfacesParameterData.objects.filter(api_test_case_id=api_interfaces_case_id).count() > 0:
                ApiInterfacesParameterData.objects.delete()
                for api_parameter in data['api_parameter']:
                    ApiInterfacesParameterData.objects.create(api_test_case_id=api_interfaces_case_id,
                                                              api_parameter_name=api_parameter['api_parameter_name'],
                                                              api_must_parameter=api_parameter['api_must_parameter'],
                                                              api_parameter_value=api_parameter['api_parameter_value'],
                                                              api_field_describe=api_parameter['api_field_describe'])
            else:
                for api_parameter in data['api_parameter']:
                    ApiInterfacesParameterData.objects.create(api_test_case_id=api_interfaces_case_id,
                                                              api_parameter_name=api_parameter['api_parameter_name'],
                                                              api_must_parameter=api_parameter['api_must_parameter'],
                                                              api_parameter_value=api_parameter['api_parameter_value'],
                                                              api_field_describe=api_parameter['api_field_describe'])

            ApiInterfacesCase.objects.filter(id=api_interfaces_case_id).update(update_time=datetime.now())
            ApiInterfacesCase.objects.filter(id=api_interfaces_case_id).update(**form.cleaned_data)

            return response_success("修改API测试用例成功")
        else:
            raise MyException()

    def delete(self, request, api_interfaces_case_id, *args, **kwargs):
        """
         删除接口测试用例
        :param request:
        :param api_interfaces_case_id:
        :param args:
        :param kwargs:
        :return:
        """

        ApiInterfacesCase.objects.delete()
        return response_success("删除API测试用例成功")


class ApiInterfacesCaseDeBugView(View):

    def post(self, request, *args, **kwargs):
        """
        API测试用例调试
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        data_payload = ''
        api_result = ''
        body = request.body

        if not body:
            return response_success()

        data = json.loads(body)
        # noinspection PyBroadException
        try:
            api_environment = APIEnvironment.objects.get(id=data['api_environment_id'])
        except Exception:
            return response_failed("30000", "请选择域名")

        # 请求地址
        api_url = api_environment.api_title + data['api_url']

        api_url = RegularMatch(api_url, data['api_environment_id'], regular="new")
        logger.info("************************")
        logger.info("请求地址： %s", api_url)
        logger.info("************************")

        if api_url[0] == "该变量数据库未找到":
            return response_failed("4000", str(api_url[0] + api_url[1]))

        api_headers = RegularMatch(data['api_headers'], data['api_environment_id'], regular="new")
        if api_headers[0] == "该变量数据库未找到":
            return response_failed("4000", str(api_headers[0] + api_headers[1]))

        json_header = api_headers.replace("\'", "\"")
        if data['api_headers'] == '':
            header = data['api_headers']
        else:
            try:
                header = json.loads(json_header)
            except json.decoder.JSONDecodeError:
                return response_failed("30000", "header类型错误" + json_header)
        logger.info(json_header)

        # Params参数
        api_parameter = {}
        for api_parameters in data['api_parameter']:
            if api_parameters['api_must_parameter'] == "true":
                api_parameter.update({api_parameters['api_parameter_name']: api_parameters['api_parameter_value']})
            else:
                pass

        api_parameter_data = RegularMatch(str(api_parameter), data['api_environment_id'], regular="new")
        if api_parameter_data[0] == "该变量数据库未找到":
            return response_failed("4000", str(api_parameter_data[0] + api_parameter_data[1]))

        data_parameter = api_parameter_data.replace("\'", "\"")
        if data_parameter == '':
            data_payload = api_parameter_data
            logger.info(data_payload)
        else:
            try:
                data_payload = json.loads(data_parameter)
                logger.info(data_payload)
            except json.decoder.JSONDecodeError:
                return response_failed("30000", "参数类型错误" + data_payload)

        api_parameter_body = RegularMatch(data['api_parameter_body'], data['api_environment_id'], regular="new")
        if api_parameter_body[0] == "该变量数据库未找到":
            return response_failed("4000", str(api_parameter_body[0] + api_parameter_body[1]))

        json_par = api_parameter_body.replace("\'", "\"")
        if api_parameter_body == '':
            payload = api_parameter_body
            logger.info(payload)
        else:
            try:
                payload = json.loads(json_par)
                logger.info(payload)
            except json.decoder.JSONDecodeError:
                return response_failed("30000", "参数类型错误" + json_par)

        r = InterfaceRequest(str(data['api_method']), str(data['api_parameter_types']), api_url, header, payload,
                             data_payload)
        logger.info("测试用例名称： %s", data['api_interfaces_case_name'])
        logger.info("请求地址： %s", r.url)
        logger.info("请求json数据： %s", payload)
        logger.info("请求parameter数据： %s", data_payload)
        logger.info("请求头： %s", r.headers)
        logger.info("请求响应： %s", r.text)

        if r == "请求超时":
            return response_failed("30000", "接口超时", {'api_url': api_url,
                                                     "api_method": int(data['api_method']),
                                                     'api_header': header,
                                                     'api_body': payload,
                                                     'api_code': "请求超时",
                                                     'api_assert': "请求超时,断言失败",
                                                     'response_message': {"results": "请求超时"},
                                                     'response_time': 0,
                                                     'api_parameter_data': api_parameter})
        # r.encoding = r.apparent_encoding
        try:
            response_message = r.json()
        except json.decoder.JSONDecodeError:
            return response_failed("30000", "接口返回结果类型错误非JSON格式", {'api_url': api_url,
                                                                  "api_method": int(data['api_method']),
                                                                  'api_header': header,
                                                                  'api_body': payload,
                                                                  'api_code': str(r.status_code),
                                                                  'response_message': r.text,
                                                                  'response_time': str(r.elapsed.total_seconds()),
                                                                  'api_parameter_data': api_parameter})

        # 断言
        if data['api_assert_type'] == '':
            result = "断言内容为空"

        elif data['api_assert_type'] == 1:

            try:

                r_text = re.sub(r'(\\u[\s\S]{4})', lambda x: x.group(1).encode("utf-8").decode("unicode-escape"), r.text)

                r_text_test = "".join(r_text.split())
                r_text_data = "".join(data['api_assert_text'].split())
                assert r_text_data in r_text_test
                result = "断言成功"
            except Exception as e:
                result = "断言失败: 响应内容中未包含 断言内容，断言内容： %s ，响应内容：%s" % (
                    data['api_assert_text'], r_text_test)
                logger.error(result + str(e))
                pass

        elif data['api_assert_type'] == 2:
            try:
                r_text = re.sub(r'(\\u[\s\S]{4})', lambda x: x.group(1).encode("utf-8").decode("unicode-escape"), r.text)
                r_text_test = "".join(r_text.split())
                r_text_data = "".join(data['api_assert_text'].split())

                assert r_text_data == r_text_test
                result = "断言成功"
            except Exception as e:
                result = "断言失败: 断言内容 %s 与响应结果不匹配，%s" % (
                    data['api_assert_text'], r_text_test)
                logger.error(result + str(e))
                pass
        elif data['api_assert_type'] == 3:

            database = APIDatabase.objects.get(id=data['dataBase'])
            db = HandleDB(database.api_host, int(database.api_port), database.user, database.password,
                          database.database)
            sql = data['database_sql']
            count = db.get_count(sql)
            db.close()
            if str(count) == str(data['api_assert_text']):
                result = '断言成功'
            else:
                result = '断言失败,查询的数据是： %s' % str(count)
        elif data['api_assert_type'] == 4:
            try:
                assert data['api_assert_text'] == str(r.status_code)
                result = "断言成功"
            except Exception as e:
                result = "断言失败: code状态码 %s 与响应状态码不匹配，%s" % (data['api_assert_text'], str(r.status_code))
                logger.error(result + str(e))
                pass

        api_variable_results = []

        for api_parameter_extraction in data['api_parameter_extraction']:
            if api_parameter_extraction['api_value_variable'] == "":
                api_parameter_extraction_dict = {
                    "api_variable_results": "无参数提取",
                    "api_value_variable": api_parameter_extraction['api_value_variable'],
                    "api_key_variable": api_parameter_extraction['api_key_variable'],
                }
                api_variable_results.append(api_parameter_extraction_dict)

            elif ApiInterfacesParameterExtraction.objects.filter(
                    api_key_variable=api_parameter_extraction['api_key_variable']).count() >= 0:
                # 提取变量
                try:
                    api_result = json.loads(r.text)
                except Exception as e:
                    logger.info('json转换失败（变量）：' + str(e))
                    pass
                v_text = api_parameter_extraction['api_value_variable'].split(".")
                logger.info('这是提取' + str(v_text))
                try:
                    api_result = ExtractParameters(v_text, api_result)
                    api_parameter_extraction_dict = {
                        "api_value_variable": api_parameter_extraction['api_value_variable'],
                        "api_key_variable": api_parameter_extraction['api_key_variable'],
                        "api_variable_results": str(api_result)
                    }

                    api_variable_results.append(api_parameter_extraction_dict)

                except Exception as e:
                    logger.info('参数提取异常' + str(e))
                    api_parameter_extraction_dict = {
                        "api_variable_results": api_parameter_extraction['api_key_variable'],
                        "api_value_variable": api_parameter_extraction['api_value_variable'],
                        "api_key_variable": api_parameter_extraction['api_key_variable'],
                    }

                    api_variable_results.append(api_parameter_extraction_dict)

                    logger.info(api_variable_results)
        return response_success({'api_url': api_url,
                                 'api_header': header,
                                 'api_body': payload,
                                 'api_code': str(r.status_code),
                                 'api_assert': str(result),
                                 "api_method": int(data['api_method']),
                                 'response_message': response_message,
                                 'response_time': str(r.elapsed.total_seconds()),
                                 'api_parameter_extraction': api_variable_results,
                                 'api_parameter_data': api_parameter})