# -*- coding: utf-8 -*-
import logging
import re
from urllib.parse import urljoin

import allure
import pytest

from joyhub_backend.library.hubops_parser import load_hubops_cases
from joyhub_backend.library.joyhub_interface import JoyhubInterface


ALL_CASES = load_hubops_cases()


def case_id(case):
    raw_id = "{}-{}".format(case.get("case_id"), case.get("name"))
    safe_id = re.sub(r"[^0-9A-Za-z_\u4e00-\u9fa5-]+", "_", raw_id)
    return safe_id[:120]


@allure.feature("JoyHub Backend 接口自动化")
class TestHubOps(object):
    test_case = JoyhubInterface()

    def teardown_method(self):
        with allure.step("后置：记录用例结束日志"):
            logging.info("-----------------------------End-------------------------------")

    @pytest.mark.parametrize("case", ALL_CASES, ids=case_id)
    def test_hub_ops_api(self, case):
        allure.dynamic.title("{} {}".format(case.get("case_id"), case.get("name")))
        allure.dynamic.story(case.get("name"))

        with allure.step("前置：初始化接口客户端并准备鉴权 token"):
            headers = case.get("headers") or {}
            query = case.get("query") or {}
            body = case.get("body") or {}

        response_data = self.test_case.request(
            case.get("name"),
            case.get("method"),
            case.get("url"),
            body=body,
            query=query,
            headers=headers,
        )
        with allure.step("断言内容：校验响应基础字段"):
            request_url = case.get("url") or ""
            full_url = request_url if request_url.startswith("http") else urljoin(self.test_case.base_url, request_url.lstrip("/"))
            if full_url.startswith(self.test_case.base_url):
                assert isinstance(response_data, dict), "断言失败原因：响应不是JSON对象，响应{}".format(response_data)
                assert "code" in response_data, "断言失败原因：响应缺少code字段，响应{}".format(response_data)
                assert response_data.get("msg") is not None, "断言失败原因：msg字段不能为空，响应{}".format(response_data)
            else:
                assert response_data is not None, "断言失败原因：非业务接口响应为空"
        logging.info("断言通过：%s", case.get("name"))
