import json
import os
import time
import allure
import pytest
import requests
from playwright.sync_api import sync_playwright, Playwright, APIRequestContext
import datetime
from BuildInLibrary.BuildInLibrary import BuildInLibrary
from Config import Config
from Utils.HTTPClient import HTTPClient
from Utils.Debug_talk import DubugTalk
from Utils.logger_util import write_log, error_log

import sys

@pytest.fixture(scope="function")
@allure.title("Generate pageobject and video of the operation")
def page():
    """
    功能：在每个用例执行之前，初始化page对象，并在用例执行完成后生成页面操作视频，作为附件添加到allure报告中
    返回：page对象
    """
    browser = None
    context = None
    page = None
    try:
        with sync_playwright() as p:
            browser = p.chromium.launch(headless=False, channel=Config.browser,
                                        args=['--start-maximized'])  # 设置headless为False以显示浏览器界面
            # 设置视频录制目录（record_video_dir）、视频分辨率（record_video_size）、视频窗口大小（no_viewport）
            context = browser.new_context(no_viewport=True, locale="zh-CN",
                                          record_video_size={"width": 1920, "height": 1080}, record_video_dir="./TestReport/Videos/",
                                          accept_downloads=True)
            page = context.new_page()
            write_log("\n-------------测试用例开始-----------")
            yield page  # 返回page对象
            write_log("\n-------------测试用例结束-----------")

            context.close()
            browser.close()

            # 将视频文件作为附件添加到Allure报告
            video_path = page.video.path()  # 获取视频路径
            # print("打印视频路径：",video_path)
            if os.path.exists(video_path):
                try:
                    allure.attach(body=open(video_path, "rb").read(),
                                  attachment_type=allure.attachment_type.WEBM,
                                  name="CMS操作的屏幕录制",)
                except Exception as e:
                    error_log(f"page fixture log:添加allure视频附件出现异常: {e}")
    except Exception as e:
        error_log(f"page fixture log:fixture log:page fixture执行过程出现异常: {e}")


@pytest.fixture(scope="class")
def global_build_in_library_object():
    """
    功能：在每个测试类运行之前，初始化内置库全局对象
    返回：内置库实例
    """
    # 在这里初始化内置库全局对象
    bl = BuildInLibrary()
    yield bl

# @pytest.hookimpl(tryfirst=True, hookwrapper=True)
# def pytest_runtest_makereport(item, call):
#     """
#     功能：获取每个用例状态的钩子函数
#     参数：
#     item: 测试用例
#     call: 测试步骤
#     """
#     # 获取钩子方法的调用结果
#     out_come = yield
#     rep = out_come.get_result()  # 从钩子方法的调用结果中获取测试报告
#     # rep.when表示测试步骤，仅仅获取用例call执行结果是失败的情况,不包含setup/teardown
#     if rep.when == "call" and rep.failed:
#         failure_log_file_name = "failure_log_" + datetime.datetime.now().strftime("%Y%m%d") + "_" + str(int(time.time())) +".log"
#         failures_log = os.path.join(Config.logs, failure_log_file_name)
#         mode = "a" if os.path.exists(failures_log) else "w"
#         with open(failures_log, mode) as f:
#             # let's also access a fixture for the fun of it
#             if "CaseData" in item.fixturenames:
#                 extra = " (%s)" % item.funcargs["CaseData"]
#             else:
#                 extra = ""
#             f.write(f"{datetime.datetime.now()}" + " " + rep.nodeid + extra + "\n")
#         pageobject = item.funcargs.get('page')  # 获取page() fixture 返回值(页面对象)
#         # 添加allure报告失败截图
#         if hasattr(pageobject, "screenshot"):
#             with allure.step('添加用例执行失败截图...'):
#                 path = Config.test_screenshot_dir + os.path.sep + "失败截图.png"
#                 # 按指定区域截图
#                 screenshot_area = {'x': Config.x_coordinate, 'y': Config.y_coordinate, 'width': Config.width,'height': Config.height}
#                 file = pageobject.screenshot(path=path, full_page=True, clip=screenshot_area)
#                 # file = pageobject.screenshot(path=path)
#                 allure.attach(file, "失败截图", allure.attachment_type.PNG)
#                 write_log("pytest_runtest_makereport log:添加失败截图成功")
#         else:
#             error_log("pytest_runtest_makereport log:添加失败截图失败")


@pytest.fixture(scope="session", autouse=True) #session
@allure.title("创建工程")
def project_init():
    """
    功能：用例执行前创建空白测试工程并初始化，用例执行完毕删除测试工程
    返回：工程ID
    """
    # 清空extract.yaml文件
    DubugTalk().clear_extract_file()

    # 清空videos路径下的所有文件
    videos_path = Config.test_video_dir
    DubugTalk().clear_folder_contents(videos_path)

    # 清空Logs路径下的所有文件
    logs_path = Config.logs
    DubugTalk().clear_folder_contents(logs_path)


    """创建空白测试工程"""
    url = Config.url+r"/api/v1/project/node"
    project_name = f"UI自动化测试项目_{str(int(time.time()))}"
    data = {"name": f"{project_name}", "path": None, "type": "1"}
    try:
        response = requests.post(url=url,data=data)
        if response.status_code!=200:
            error_log(f"工程创建失败,状态码为{response.status_code}")
        else:
            data = {"project_id": response.text}
            # 写入extract.yml文件
            DubugTalk().write_extract_file(data)
    except Exception as e:
        error_log(f"工程创建失败:{e}")

    """获取工程id X_project"""
    project_id = DubugTalk().read_extract_file("project_id")
    url = Config.url + rf"/api/v1/project/{project_id}/info"
    try:
        response = requests.get(url=url)
        if response.status_code != 200:
            error_log(f"获取工程信息失败,状态码为{response.status_code}")
        else:
            data = {"x_project": response.json()["identifier"]}
            # 写入extract.yml文件
            DubugTalk().write_extract_file(data)

    except Exception as e:
        error_log(f"获取工程信息失败:{e}")

@pytest.fixture(scope="session", autouse=True)
def upload_image():
    """
    在图库中上传图片，图片名为“皮卡丘.jpg”
    :return:
    """
    url = Config.url+r"/api/v1/view/image/gallery?group=我的\Default"
    x_project = DubugTalk().read_extract_file("x_project")
    headers= {'X-Project': f"{x_project}"}
    file_path = Config.test_project_dir + r"\Gallery\皮卡丘.jpg"
    #文件数据
    files = {'formFiles': open(file_path,'rb')}
    try:
        re = requests.post(url=url, headers=headers, files=files)
        if re.status_code != 200:
            error_log(f"上传图片失败，状态码为{re.status_code}")
    except Exception as e:
        error_log(f"上传图片失败:{e}")


@pytest.fixture(scope="function", autouse=False)
def create_and_destroy_page():
    """
    测试用例执行前创建画面，执行结束删除画面
    :return:
    """
    # 新建画面
    response = None
    newpage_url = Config.url+r"/api/v1/view/node?copyFrom="
    x_project = DubugTalk().read_extract_file("x_project")
    headers = {'X-Project': f"{x_project}"}
    PageName = "画面" + str(int(time.time()))
    data = {"name": f"{PageName}", "parentId": None, "type": 1, "sort": 1}
    try:
        response = requests.post(url=newpage_url, headers=headers, json=data)
        if response.status_code != 200:
            error_log(f"画面创建失败，状态码为{response.status_code}")
    except Exception as e:
        error_log(f"页面创建失败:{e}")

    yield
    # 删除画面
    delpage_url = Config.url + r"/api/v1/view/node/"+response.text
    x_project = DubugTalk().read_extract_file("x_project")
    headers = {'X-Project': f"{x_project}"}
    try:
        re = requests.delete(url=delpage_url, headers=headers)
        if re.status_code != 200:
            error_log(f"画面删除失败，状态码为{re.status_code}")
    except Exception as e:
        error_log(f"页面删除失败:{e}")



