# -*- coding: utf-8 -*-
# @Time : 2022/7/20 10:30
# @Author : wangyinghao
# @Site : 
# @File : api_scenarios_case_view.py
# @Software: PyCharm
from django.views.generic import View
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_database import APIDatabase
from automated_main.models.api_automation.api_environment import APIEnvironment
from automated_main.utils.handle_db import HandleDB
from automated_main.utils.api_utils import RegularMatch, InterfaceRequest, ExtractParameters
from automated_main.models.api_automation.api_scenarios_case import ApiScenariosCaseAssociated, ApiScenariosCase
from automated_main.models.api_automation.api_interfaces_case import ApiInterfacesCase, \
    ApiInterfacesParameterExtraction, ApiInterfacesParameterData
from automated_main.form.api_scenarios_case import ApiScenariosCaseForm
from automated_main.models.api_automation.api_management import ApiManagement
from datetime import datetime
import arrow
import ast
import json
import re

import logging

logger = logging.getLogger('django')


class ApiScenariosCaseView(View):

    def get(self, request, api_management_id, *args, **kwargs):
        """
        获取场景用例列表
        :param request:
        :param args:
        :param api_management_id:
        :param kwargs:
        :return:
        """
        api_scenarios_case_data = ApiScenariosCase.objects.filter(api_management_id=api_management_id)

        api_scenarios_case_data_list = []

        for api_scenarios_case in api_scenarios_case_data:
            api_scenarios_case_data_dict = {
                "id": api_scenarios_case.id,
                "api_scenarios_case_name": api_scenarios_case.api_scenarios_case_name,
                "api_scenarios_case_describe": api_scenarios_case.api_scenarios_case_describe,
                "update_time": arrow.get(str(api_scenarios_case.update_time)).format('YYYY-MM-DD HH:mm:ss'),
                "create_time": arrow.get(str(api_scenarios_case.create_time)).format('YYYY-MM-DD HH:mm:ss')
            }

            api_scenarios_case_data_list.append(api_scenarios_case_data_dict)

        return response_success(api_scenarios_case_data_list)

    def delete(self, request, scenarios_case_id, *args, **kwargs):
        """
        删除场景测试用例
        :param request:
        :param args:
        :param scenarios_case_id:
        :param kwargs:
        :return:
        """
        ApiScenariosCase.objects.get(id=scenarios_case_id).delete()

        return response_success("删除API测试用例成功")

    def put(self, request, *args, **kwargs):
        """
        创建API场景测试
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        body = request.body
        if not body:
            return response_success()
        data = json.loads(body)
        form = ApiScenariosCaseForm(data)
        if form.is_valid():
            api_scenarios_case = ApiScenariosCase.objects.create(**form.cleaned_data)
            api_scenarios_case_id = api_scenarios_case.id

            for i in data["api_scenarios_case_data"]:
                api_interfaces_case_id = (i['api_interfaces_case_id'])
                case_steps = (i['case_steps'])
                ApiScenariosCaseAssociated.objects.create(sid_id=api_scenarios_case_id,
                                                          interfaces_case_id=api_interfaces_case_id,
                                                          case_steps=case_steps
                                                          )

            return response_success("创建API业务测试用例成功")
        else:
            raise MyException()

    def post(self, request, scenarios_case_id, *args, **kwargs):
        """
        编辑API场景测试
        :param request:
        :param args:
        :param scenarios_case_id:
        :param kwargs:
        :return:
        """
        api_scenarios_case = ApiScenariosCase.objects.get(id=scenarios_case_id)
        if api_scenarios_case is None:
            return response_success()
        body = request.body
        if not body:
            return response_success()
        data = json.loads(body)
        form = ApiScenariosCaseForm(data)

        api_scenarios_case.api_scenarios_case_name = data['api_scenarios_case_name']
        api_scenarios_case.api_scenarios_case_describe = data['api_scenarios_case_describe']
        api_scenarios_case.api_management_id = data['api_management_id']
        api_scenarios_case.update_time = datetime.now()
        api_scenarios_case.save()
        ApiScenariosCaseAssociated.objects.filter(sid_id=api_scenarios_case.id).delete()

        if form.is_valid():
            for i in data["api_scenarios_case_data"]:
                api_interfaces_case_id = (i['api_interfaces_case_id'])
                case_steps = (i['case_steps'])

                ApiScenariosCaseAssociated.objects.create(sid_id=api_scenarios_case.id,
                                                          interfaces_case_id=api_interfaces_case_id,
                                                          case_steps=case_steps)
            return response_success("编辑API场景测试用例成功")
        else:
            raise MyException()


class ApiScenariosCaseGetView(View):

    def get(self, request, scenarios_case_id, *args, **kwargs):
        """
        获取场景用例-组合
        :param request:
        :param args:
        :param scenarios_case_id:
        :param kwargs:
        :return:
        """
        api_scenarios_case_associated_data = ApiScenariosCaseAssociated.objects.filter(sid_id=scenarios_case_id)

        api_scenarios_case_associated_data_list = []
        for api_scenarios_case_associated in api_scenarios_case_associated_data:
            api_case = ApiInterfacesCase.objects.get(id=api_scenarios_case_associated.interfaces_case_id)

            interfaces_name = ApiManagement.objects.get(id=api_case.api_management_id)

            api_module_name = ApiManagement.objects.get(id=interfaces_name.parent)

            api_service_name = ApiManagement.objects.get(id=api_module_name.parent)

            api_scenarios_case_associated_dict = {
                "case_steps": api_scenarios_case_associated.case_steps,
                "api_scenarios_case_name": api_scenarios_case_associated.interfaces_case.api_interfaces_case_name,
                "api_interfaces_case_id": api_scenarios_case_associated.interfaces_case.id,
                "interfaces_name": interfaces_name.name,
                "api_module_name": api_module_name.name,
                "api_service_name": api_service_name.name,

            }
            api_scenarios_case_associated_data_list.append(api_scenarios_case_associated_dict)

        return response_success(api_scenarios_case_associated_data_list)


class ApiScenariosCaseDebugView(View):

    def post(self, request, *args, **kwargs):
        """
        API场景测试DEBUG
        :param request:
        :param args:
        :param kwargs:
        :return:
        """

        body = request.body
        if not body:
            return response_success()
        data = json.loads(body)
        for case in data['api_scenarios_case_data']:
            interfaces_case = ApiInterfacesCase.objects.get(id=case['api_interfaces_case_id'])

            api_environment = APIEnvironment.objects.get(id=data['environment'])
            # 请求地址
            api_url = api_environment.api_title + interfaces_case.api_url

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

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

            json_header = api_headers.replace("\'", "\"")
            if interfaces_case.api_headers == '':
                header = interfaces_case.api_headers
            else:
                try:
                    header = json.loads(json_header)
                except json.decoder.JSONDecodeError:
                    return response_failed('30000', "header类型错误，用例名称: " + str(interfaces_case.api_interfaces_case_name))
            logger.info(json_header)

            api_parameter_body = RegularMatch(interfaces_case.api_parameter_body, data['environment'], regular="new")
            if api_parameter_body[0] == "该变量数据库未找到":
                return response_failed('40000', "该变量数据库未找到，用例名称: " + str(
                    interfaces_case.api_interfaces_case_name) + "\n" + "变量值：" +
                                       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', "参数类型错误，用例名称: " + str(interfaces_case.api_interfaces_case_name))

            parameter_data = ApiInterfacesParameterData.objects.filter(api_test_case_id=case['api_interfaces_case_id'])
            api_parameter_dict = {}
            for api_parameters in parameter_data:
                if api_parameters.api_must_parameter == "true":
                    api_parameter_dict.update(
                        {api_parameters.api_parameter_name: api_parameters.api_parameter_value})
                else:
                    pass
            if api_parameter_dict == {}:
                api_parameter_data = {}
            else:
                api_parameter_data = RegularMatch(str(api_parameter_dict), data['environment'], regular="new")

            if api_parameter_data == {}:
                data_payload = api_parameter_data
                logger.info(data_payload)
            else:
                try:
                    data_payload = ast.literal_eval(api_parameter_data)
                except json.decoder.JSONDecodeError:
                    return response_failed("30000", "Parameter参数类型错误" + api_parameter_data)

            r = InterfaceRequest(str(interfaces_case.api_method), str(interfaces_case.api_parameter_types),
                                 api_url, header, payload, data_payload)

            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', "接口请求超时:" + str(interfaces_case.api_interfaces_case_name))

            try:
                response_message = r.json()
            except json.decoder.JSONDecodeError:
                return response_failed('30000', "接口返回结果类型错误非JSON格式:" + str(
                    interfaces_case.api_interfaces_case_name) + "\n" + str(r.text))

            # 断言
            if interfaces_case.api_assert_type == '':
                result = "断言内容为空"
                logger.error(result)

            elif interfaces_case.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(interfaces_case.api_assert_text.split())
                    assert r_text_data in r_text_test
                except Exception as e:
                    result = "断言失败: 响应内容中未包含 断言内容，断言内容： %s ，响应内容：%s" % (
                        interfaces_case.api_assert_text, r_text)
                    logger.error(result + str(e))
                    return response_failed('30000',
                                           "断言失败，用例名称: " + str(interfaces_case.api_interfaces_case_name) + "\n" +
                                           "断言结果：" + result)
            elif interfaces_case.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(interfaces_case.api_assert_text.split())
                    assert r_text_data == r_text_test
                except Exception as e:
                    result = "断言失败: 断言内容 %s 与响应结果不匹配，%s" % (
                        interfaces_case.api_assert_text, r_text)
                    logger.error(result, e)
                    return response_failed('30000',
                                           "断言失败，用例名称: " + str(interfaces_case.api_interfaces_case_name) + "\n" +
                                           "断言结果：" + result)
            elif interfaces_case.api_assert_type == 3:

                database = APIDatabase.objects.get(id=interfaces_case.dataBase_id)
                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(interfaces_case.api_assert_text):
                    result = '断言成功'
                    logger.error(result)
                else:
                    result = '断言失败,查询的数据是： %s' % str(count)
                    logger.error(result)
                    return response_failed('30000',
                                           "断言失败，用例名称: " + str(interfaces_case.api_interfaces_case_name) + "\n" +
                                           "断言结果：" + result)
            elif interfaces_case.api_assert_type == 4:
                try:
                    assert interfaces_case.api_assert_text == str(r.status_code)
                    result = "断言成功"
                except Exception as e:
                    result = "断言失败: code状态码 %s 与响应状态码不匹配，%s" % (interfaces_case.api_assert_text, str(r.status_code))
                    logger.error(result + str(e))
                    return response_failed('30000',
                                           "断言失败，用例名称: " + str(interfaces_case.api_interfaces_case_name) + "\n" +
                                           "断言结果：" + result)

            parameter_extraction = ApiInterfacesParameterExtraction.objects.filter(
                api_test_case_id=case['api_interfaces_case_id'])

            if parameter_extraction == "" or None:
                pass
            else:
                # 提取变量
                try:
                    api_result = json.loads(r.text)
                except Exception as e:
                    logger.info('json转换失败（变量）：' + str(e))
                    pass
                for parameter_extractions in parameter_extraction:
                    v_text = parameter_extractions.api_value_variable.split(".")
                    try:
                        api_results = ExtractParameters(v_text, api_result)
                        api_parameter_extraction = ApiInterfacesParameterExtraction.objects.get(
                            api_key_variable=str(parameter_extractions.api_key_variable))
                        api_parameter_extraction.api_variable_results = str(api_results)
                        api_parameter_extraction.save()
                    except Exception as e:
                        logger.info('参数提取失败' + str(e))
                        return response_failed('30000', "参数提取失败，用例名称:" +
                                               str(interfaces_case.api_interfaces_case_name) + '\n' + "异常信息：" + str(e))

        return response_success("调试成功")
