# -*- coding: utf-8 -*-
import json
import pytest
import allure
from pathlib import Path
from api_auto_framework.core.request_wrapper import RequestWrapper
from api_auto_framework.utils.data_loader import load_test_data
from api_auto_framework.utils.assertion_tools import cookie
from api_auto_framework.utils.handle_path import testData_path

# 文件路径
TEST_DATA = Path(testData_path) / "test_Baidu_Advertiser_getList.yaml"


def prepare_request_kwargs(test_data):
    """准备请求参数"""
    kwargs = {
        "method": test_data['method'],
        "url": test_data['url'],
        "headers": test_data.get('headers'),
        "cookies": cookie()
    }

    # 智能处理请求体
    body = test_data.get('body')
    if body is not None:
        if isinstance(body, (dict, list)):
            kwargs["json"] = body
        else:
            kwargs["data"] = body

    return kwargs, body


def attach_request_details(url, body):
    """在Allure中附加请求详情"""
    with allure.step("准备请求数据"):
        allure.attach(f"URL: {url}", "请求URL")
        if body:
            allure.attach(json.dumps(body, indent=2, ensure_ascii=False),
                          "请求体", allure.attachment_type.JSON)


def attach_response_details(response, result):
    """在Allure中附加响应详情"""
    with allure.step("响应结果"):
        allure.attach(str(response.status_code), "响应状态", allure.attachment_type.TEXT)
        # allure.attach(response.text, "原始响应内容", allure.attachment_type.TEXT)

        if result:
            allure.attach(str(result["body"]["code"]), "响应状态码", allure.attachment_type.TEXT)
            allure.attach(json.dumps(result["headers"], indent=2),
                          "响应头", allure.attachment_type.JSON)
            if result["body"]:
                body_str = json.dumps(result["body"], indent=2, ensure_ascii=False) if isinstance(result["body"],
                                                                                                  dict) else str(
                    result["body"])
                allure.attach(body_str, "响应内容", allure.attachment_type.JSON)


def perform_assertions(result, expected):
    """执行断言并处理失败情况"""
    try:
        # 状态码断言
        assert result["status_code"] == expected["status_code"], \
            f"状态码不匹配: {result['status_code']} ≠ {expected['status_code']}"

        # 业务码断言
        assert result["body"]["code"] == 0, f"业务码非零: {result['body']['code']}"

        # 消息断言
        assert result["body"]["message"] == "成功", f"消息不符: {result['body']['message']}"

    except AssertionError as e:
        # 在Allure中记录断言失败详情
        allure.attach(str(e), "断言失败详情", allure.attachment_type.TEXT)
        raise
    except KeyError as e:
        # 处理响应体中缺少必要字段的情况
        error_msg = f"响应体中缺少关键字段: {str(e)}"
        allure.attach(error_msg, "响应体结构错误", allure.attachment_type.TEXT)
        pytest.fail(error_msg)


@allure.feature("百度")
@allure.story("媒体账户")
@allure.title("获取媒体账户列表")
@pytest.mark.generated
def test_Baidu_Advertiser_getList():
    """主面板查询媒体账户列表"""
    # 加载测试数据
    test_data = load_test_data(TEST_DATA)[0]

    # 准备请求参数
    request_kwargs, body = prepare_request_kwargs(test_data)

    # 附加请求详情到报告
    attach_request_details(request_kwargs["url"], body)

    # 发送请求
    with allure.step("发起请求: test_Baidu_Advertiser_getList"):
        response = RequestWrapper.send_request(**request_kwargs)

        # 检查状态码
        if response.status_code != 200:
            error_msg = f"请求失败，状态码: {response.status_code}"
            allure.attach(error_msg, "请求错误", allure.attachment_type.TEXT)
            pytest.fail(error_msg)

    # 处理响应
    with allure.step("处理响应"):
        try:
            result = RequestWrapper.formatted_response(response)
        except Exception as e:
            error_msg = f"响应处理失败: {str(e)}"
            allure.attach(error_msg, "响应处理错误", allure.attachment_type.TEXT)
            allure.attach(response.text, "原始响应内容", allure.attachment_type.TEXT)
            pytest.fail(error_msg)

    # 附加响应详情到报告
    attach_response_details(response, result)

    # 执行断言
    perform_assertions(result, test_data["expected"])