import settings
from settings import sendSocketMessage
from .detail_func import *
import json
from .base import *

# from .match_and_cutout_mode_control.base_deal_image_v2 import BaseDealImage
# from module.view_control.MineQWidget import DialogShow, WorkerOneThread
import threading
from concurrent.futures import ThreadPoolExecutor
import concurrent.futures
from .data import DataModeGenerateDetail
import time
from PIL import Image
from io import BytesIO
import os, re
from functools import partial

# from multiprocessing import Process, Queue
import pickle
from .base_deal import BaseDealImage
from middleware import UnicornException
from settings import recordDataPoint
import asyncio


class RunMain:
    # run_end_sign = Signal(dict)
    # show_dialog_sign = Signal(dict)
    # show_progress_detail_sign = Signal(str)

    # # 定义一个信号用于请求显示对话框
    # show_dialog_signal = Signal()
    # # 定义一个信号用于返回对话框的结果
    # dialog_result_signal = Signal(str)

    # dialog_result_signal = Signal(str)

    def __init__(self, windows, token, uuid):
        super().__init__()
        self.windows = windows
        self.token = token
        self.uuid = uuid
        self.dialog_result = ""
        self.data_mode_generate_detail = DataModeGenerateDetail(token=token)
        # self.dialog_result_signal.connect(self.on_dialog_result)
        self.event = threading.Event()

    def set_state(self, state_value: int):
        # 0禁用  1进行中  2已结束
        if state_value not in [0, 1, 2, 99]:
            return
        # self.windows.change_state_sign.emit(state_value)
        # self.windows.set_state(state_value)

    # 抠图前先做数据规整处理；类似详情图生成逻辑
    def check_before_cutout(self, config_data):
        return_data = {
            "code": 99,
            "message": "",
            "data": {
                "all_goods_art_no_folder_data": [],
                "config_data": config_data,
            },
        }

        image_dir = config_data["image_dir"]
        image_order = config_data["image_order"]
        is_check_number = config_data["is_check_number"]
        is_filter = config_data["cutout_is_pass"]
        resize_image_view = config_data["resize_image_view"]
        goods_art_nos = config_data["goods_art_nos"]
        logo_path = config_data["logo_path"]
        cutout_mode = config_data["cutout_mode"]  # 是否精细化抠图，默认为普通抠图
        special_goods_art_no_folder_line = config_data[
            "special_goods_art_no_folder_line"
        ]
        # 自动处理红蜻蜓货号，进行重命名
        # if settings.PROJECT == "红蜻蜓":
        #     # 规整红蜻蜓货号图
        #     all_goods_art_no_folder_data = get_all_goods_art_no_folder(path=image_dir)
        #     BaseDealImage().rename_folder_for_hqt(all_goods_art_no_folder_data=all_goods_art_no_folder_data)
        # 重新获取文件夹信息
        all_goods_art_no_folder_data = get_all_goods_art_no_folder(
            path=image_dir, goods_art_nos=goods_art_nos
        )
        print("all_goods_art_no_folder_data", all_goods_art_no_folder_data)
        f = True
        is_do_other = False
        if is_do_other:
            for i in all_goods_art_no_folder_data:
                i["label"] = "不处理"
            is_filter = False
            specified_goods_art_no_folder = special_goods_art_no_folder_line
            specified_goods_art_no_folder = specified_goods_art_no_folder.strip()
            specified_goods_art_no_folder = specified_goods_art_no_folder.replace(
                "，", ","
            )
            specified_goods_art_no_folder_list = specified_goods_art_no_folder.split(
                ","
            )
            specified_goods_art_no_folder_list = [
                x for x in specified_goods_art_no_folder_list if x
            ]
            if not specified_goods_art_no_folder_list:
                return_data[
                    "message"
                ] += "请手动输入文件夹名称（多选），或关闭指定文件夹模式\n"
            else:
                for i in all_goods_art_no_folder_data:
                    if i["folder_path"] in specified_goods_art_no_folder_list:
                        i["label"] = "待处理"
            # 哪些数据不合规
            all_folder_name_list = [
                x["folder_name"] for x in all_goods_art_no_folder_data
            ]
            for goods_art_no_folder_name in specified_goods_art_no_folder_list:
                if goods_art_no_folder_name not in all_folder_name_list:
                    return_data[
                        "message"
                    ] += "文件夹：{}，在您选的目录下不存在\n".format(
                        goods_art_no_folder_name
                    )
                    f = False

        if not f:
            # raise UnicornException(return_data["message"])
            self.set_state(state_value=2)
            return

        # 清空指定文件夹的已抠图文件
        if is_do_other:
            for folder_data in all_goods_art_no_folder_data:
                goods_art_no_folder_path = "{}/原始图_已抠图".format(
                    folder_data["folder_path"]
                )
                if os.path.exists(goods_art_no_folder_path):
                    remove_all_file(goods_art_no_folder_path)

        return_data["data"]["succeed_folder_list"] = 1

        # ==================检查填写的图片视角是否符合要求
        res = BaseDealImage(token=self.token).getImageOrder(
            image_order=image_order, resize_image_view=resize_image_view
        )
        if res["code"] != 0:
            return_data["message"] += "{}\n".format(res["msg"])
            # raise UnicornException(return_data["message"])
            return return_data
        else:
            # 图片命名顺序
            image_order_list = res["imageOrderList"]
            print("图片命名顺序", image_order_list, all_goods_art_no_folder_data)
            for goods_art_no_folder_data in all_goods_art_no_folder_data:
                if goods_art_no_folder_data["label"] != "待处理":
                    continue
                goods_art_no_folder_data["image_order_list"] = image_order_list

        # ================是否过滤已有生成的文件夹
        if is_filter:
            for goods_art_no_folder_data in all_goods_art_no_folder_data:
                if goods_art_no_folder_data["label"] != "待处理":
                    continue
                folder_path = goods_art_no_folder_data["folder_path"]
                _p = "{}/800x800".format(folder_path)
                if os.path.exists(_p):
                    if len(os.listdir(_p)):
                        goods_art_no_folder_data["label"] = "不处理"

        # ================检查每个货号文件夹图片数量是否符合要求
        all_goods_art_no_folder_data, message = BaseDealImage(
            token=self.token
        ).check_folders_image_amount(all_goods_art_no_folder_data, image_order_list)
        if message:
            return_data["message"] += "{}\n".format(message)
        return_data["code"] = 0
        return_data["data"][
            "all_goods_art_no_folder_data"
        ] = all_goods_art_no_folder_data
        return_data["data"]["image_dir"] = image_dir
        return_data["data"]["resize_image_view"] = resize_image_view
        return_data["data"]["cutout_mode"] = cutout_mode
        return_data["data"]["image_order_list"] = image_order_list
        return_data["data"]["logo_path"] = logo_path
        return return_data

    # 抠图校验后的回调函数处理
    def check_for_cutout_image_first_call_back(self, return_data):
        # return_data = {
        #     "code": 99,
        #     "message": "",
        #     "data": {
        #         "all_goods_art_no_folder_data": [],
        #     },
        # }
        code = return_data["code"]
        config_data = return_data["data"]["config_data"]
        config_data["sign_text"] = ""
        if code != 0:
            # self.windows.show_message(return_data["message"])
            # self.show_progress_detail(return_data["message"])
            # _dialog_dict = {"text": return_data["message"],
            #                 "windows": self,
            #                 }
            raise UnicornException(return_data["message"])

        do_next = False
        text = ""
        all_goods_art_no_folder_data = return_data["data"][
            "all_goods_art_no_folder_data"
        ]
        button_1, button_2, button_3 = None, None, None
        text += return_data["message"]
        # 存在错误文件夹
        error_folder = [x for x in all_goods_art_no_folder_data if x["label"] == "错误"]
        todo_folder = [
            x for x in all_goods_art_no_folder_data if x["label"] == "待处理"
        ]
        if error_folder:
            button_2 = "移除错误文件"
        if error_folder and todo_folder:
            button_1 = "移除并继续"
            button_3 = "继续(忽略其他)"
        if not error_folder and todo_folder:
            button_1 = "继续"
            # do_next = True
        text += "\n==================\n错误数据：{}个，校验无误数据：{}个".format(
            len(error_folder), len(todo_folder)
        )
        self.show_progress_detail(text)
        if button_1 is None and button_2 is None and button_3 is None:
            pass
        elif button_1 == "继续" and button_2 is None and button_3 is None:
            do_next = True
        else:
            # print("runmain  179----------------")
            # # print(self)
            # # print(self.windows)
            # _dialog_dict = {"text": text,
            #                 "button_1": button_1,
            #                 "button_2": button_2,
            #                 "button_3": button_3,
            #                 "windows": self,
            #                 }
            # self.show_dialog_sign.emit(_dialog_dict)
            # # self.exec_()
            # # 等待事件被设置
            # self.event.wait()
            # print("self.dialog_result", self.dialog_result)
            # #
            # # my_dialog = DialogShow(self.windows, text=text, button_1=button_1, button_2=button_2,
            # #                        button_3=button_3)
            # # ret = my_dialog.exec()
            # print("460  ===============my_dialog.flag_name===============")
            # print(my_dialog.flag_name)

            if "移除" in self.dialog_result:
                for error_folder_data in [
                    x for x in all_goods_art_no_folder_data if x["label"] == "错误"
                ]:
                    self.move_error_folders(
                        one_path=error_folder_data["folder_path"],
                        target_folder="{}/软件-处理失败".format(
                            config_data["image_dir"]
                        ),
                    )
            if "继续" in self.dialog_result:
                do_next = True
        goods_arts = [
            goods_art_no_folder_data["folder_name"]
            for goods_art_no_folder_data in all_goods_art_no_folder_data
        ]
        # try:
        #     loop = asyncio.get_event_loop()
        #     loop.create_task(sendSocketMessage(
        #         code=0,
        #         msg="开始处理抠图",
        #         data={
        #             "status": "进行中",
        #             "goods_art_nos": goods_arts,
        #         },
        #         msg_type="segment_progress",
        #     ))
        # except:
        #     print('An exception occurred')
        #     asyncio.run(sendSocketMessage(
        #         code=0,
        #         msg="开始处理抠图",
        #         data={
        #             "status": "进行中",
        #             "goods_art_nos": goods_arts,
        #         },
        #         msg_type="segment_progress",
        #     ))
        if do_next:
            all_goods_art_no_folder_data = [
                x for x in all_goods_art_no_folder_data if x["label"] == "待处理"
            ]
            print("===============all_goods_art_no_folder_data===============")
            print(all_goods_art_no_folder_data)

            new_func = self.do_run_cutout_image(
                all_goods_art_no_folder_data=all_goods_art_no_folder_data,
                callback_func=self.show_progress_detail,
                image_order_list=return_data["data"]["image_order_list"],
                cutout_mode=return_data["data"]["cutout_mode"],
                resize_image_view=return_data["data"]["resize_image_view"],
                windows=None,
                logo_path=return_data["data"]["logo_path"],
                config_data=config_data,
            )
            return new_func
        else:
            print("已结束抠图处理")
            # try:
            #     loop = asyncio.get_event_loop()
            #     loop.create_task(
            #         sendSocketMessage(
            #             code=0,
            #             msg="抠图结束",
            #             data={
            #                 "status": "已完成",
            #                 "goods_art_nos": goods_arts,
            #             },
            #             msg_type="segment_progress",
            #         )
            #     )
            # except:
            #     print('An exception occurred')
            #     asyncio.run(
            #         sendSocketMessage(
            #             code=0,
            #             msg="抠图结束",
            #             data={
            #                 "status": "已完成",
            #                 "goods_art_nos": goods_arts,
            #             },
            #             msg_type="segment_progress",
            #         )
            #     )
            return True

    def do_run_cutout_image(
        self,
        all_goods_art_no_folder_data,
        callback_func,
        image_order_list,
        cutout_mode,
        resize_image_view,
        windows,
        logo_path,
        config_data,
    ):
        try:
            loop = asyncio.get_event_loop()
        except:
            loop = asyncio.new_event_loop()
        executor = ThreadPoolExecutor(max_workers=10)
        goods_arts = [
            goods_art_no_folder_data["folder_name"]
            for goods_art_no_folder_data in all_goods_art_no_folder_data
        ]
        print("BaseDealImage().run_main========>>>>")
        deal = BaseDealImage(token=self.token)
        try:
            loop.run_in_executor(
                executor,
                deal.run_main(
                    all_goods_art_no_folder_data=all_goods_art_no_folder_data,
                    callback_func=callback_func,
                    image_order_list=image_order_list,
                    cutout_mode=cutout_mode,
                    resize_image_view=resize_image_view,
                    windows=windows,
                    logo_path=logo_path,
                ),
            )
        except UnicornException as e:
            raise UnicornException(e.msg)
        except Exception as e:
            raise UnicornException(e)
        # deal.run_main(
        #     all_goods_art_no_folder_data=all_goods_art_no_folder_data,
        #     callback_func=callback_func,
        #     image_order_list=image_order_list,
        #     cutout_mode=cutout_mode,
        #     resize_image_view=resize_image_view,
        #     windows=windows,
        #     logo_path=logo_path,
        # )

        recordDataPoint(
            token=self.token,
            uuid=self.uuid,
            page="抠图结束",
            data=goods_arts,
        )
        # try:
        #     loop = asyncio.get_event_loop()
        #     loop.create_task(
        #             sendSocketMessage(
        #                 code=0,
        #                 msg="抠图结束",
        #                 data={
        #                     "status": "已完成",
        #                     "goods_art_nos": goods_arts,
        #                 },
        #                 msg_type="segment_progress",
        #             )
        #         )
        # except:
        #     asyncio.run(
        #         sendSocketMessage(
        #             code=0,
        #             msg="抠图结束",
        #             data={
        #                 "status": "已完成",
        #                 "goods_art_nos": goods_arts,
        #             },
        #             msg_type="segment_progress",
        #         )
        #     )
        callback_func("已结束抠图处理")
        return True

    def do_run_cutout_image1111(
        self,
        all_goods_art_no_folder_data,
        callback_func,
        image_order_list,
        cutout_mode,
        resize_image_view,
        windows,
        logo_path,
        config_data,
    ):

        max_workers = 1
        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
            futures = []
            futures.append(
                executor.submit(
                    BaseDealImage().run_main,
                    all_goods_art_no_folder_data=all_goods_art_no_folder_data,
                    callback_func=callback_func,
                    image_order_list=image_order_list,
                    cutout_mode=cutout_mode,
                    resize_image_view=resize_image_view,
                    windows=windows,
                    logo_path=logo_path,
                )
            )

            # 使用 wait 方法等待所有任务完成
            done, not_done = concurrent.futures.wait(futures, timeout=60)
            # 处理完成的任务
            for future in done:
                if settings.IS_TEST:
                    result = future.result()
                else:
                    try:
                        result = future.result()
                    except BaseException as e:
                        print("2039 图片处理失败.{}".format(e))
                        callback_func("2039 处理失败.{}".format(e))

        # ==============完成处理==============

        # self.set_state(state_value=2)
        callback_func("已结束抠图处理")
        config_data["sign_text"] = "已结束抠图处理"
        self.run_end_sign.emit(config_data)

    def check_before_detail(self, config_data):

        # =============
        # 整体数据校验，返回错误内容，以及
        # temp_name:模板名称
        """
        步骤：
        1、 整体文件夹检查，并输出数据结构
        2、数据进行对应规整（可能有excel，红蜻蜓等）
        3、执行单个款数据处理
        """
        return_data = {
            "code": 99,
            "message": "",
            "data": {
                "error_folder_list": [],
                "goods_no_dict": {},
                "succeed_folder_list": [],
                "temp_name": config_data["temp_name"],
                "temp_name_list": config_data["temp_name_list"],
                "assigned_page_dict": config_data["assigned_page_dict"],
                "excel_temp_goods_no_data": {},  # 表格数据可能存在多模板，数据结构为一个款号下的多个模板的数据列表
                "finally_goods_no_need_temps": {},  # 每个款号需要生成的模板数据
                "config_data": config_data,
            },
        }
        temp_name = config_data["temp_name"]
        temp_name_list = config_data["temp_name_list"]
        assigned_page_dict = config_data["assigned_page_dict"]
        image_dir = config_data["image_dir"]
        is_use_excel = config_data["is_use_excel"]
        excel_path = config_data["excel_path"]
        temp_class = config_data["temp_class"]
        goods_art_nos = config_data["goods_art_nos"]
        is_check_color_is_all = config_data["is_check_color_is_all"]
        detail_is_pass = config_data["detail_is_pass"]
        error_folder_list = []
        # 遍历货号获取所有货号--可能为编号
        folder_name_list = get_all_dir_info(
            image_dir=image_dir, goods_art_nos=goods_art_nos
        )
        print("folder_name_list--folder_name_list===========>>>>", folder_name_list)
        if not folder_name_list:
            return_data["message"] += "不存在任何货号/编号文件夹\n"
            print("不存在任何货号/编号文件夹")
            return return_data

        # =========================组装数据---数据来源多种途径=========================
        _result = {"code": 99, "message": "无法解析到数据，请检查登录企业"}
        print("is_use_excel", is_use_excel)
        if not is_use_excel:
            if settings.PROJECT == "红蜻蜓":
                # goods_no_dict输出为文件夹下涉及到的所有款为key的字典，后续通过解析字典，进行提取对应文件夹
                _result = self.data_mode_generate_detail.get_basic_goods_art_data_by_hqt_and_hlm(
                    folder_name_list
                )

            elif settings.PROJECT == "惠利玛":
                if settings.Company:
                    if "惠利玛" in settings.Company:
                        _result = self.data_mode_generate_detail.get_basic_goods_art_data_by_hqt_and_hlm(
                            folder_name_list
                        )
        else:
            keys = settings.keys
            _result = (
                self.data_mode_generate_detail.get_basic_goods_art_data_form_excel(
                    folder_name_list,
                    excel_path,
                    keys,
                )
            )
            print("打印=======>>>>>>>_result=============>", _result)
        if _result["code"] == 0:
            remote_data = _result["data"]
        else:
            print('_result["message"]====>', _result["message"])
            return_data["message"] += _result["message"] + "\n"
            return return_data
        # print(json.dumps(remote_data))
        # =========================拼接数据组合为款数据=========================
        """
        1、获取所有文件夹基础数据内容
        2、结合上述返回结果进行数据组合拼接
        3、输出结果为按款为主键信息
        4、注意模板ID
        """
        print("temp_class====>", temp_class)
        print("temp_class====>", temp_name)
        # 获取所有文件夹基础数据内容  检查不满足要求的文件不满足要求移动到错误文件夹
        need_view_list = temp_class[temp_name].need_view
        _all_dir_info_data = get_all_dir_info_and_pic_info(
            image_dir, folder_name_list, need_view_list
        )
        all_dir_info_data = {}
        for one_folder, value in _all_dir_info_data.items():
            if "message" in value:
                if value["message"]:
                    error_folder_list.append(
                        {
                            "folder_name": one_folder,
                            "folder_path": "{}/{}".format(image_dir, one_folder),
                        }
                    )
                    return_data["message"] += "文件夹：{} 结构错误：{}\n".format(
                        one_folder, value["message"]
                    )
                    return_data["data"]["config_data"]["success_handler"].append(
                        {
                            "goods_art_no": one_folder,
                            "success": False,
                            "info": value["message"],
                        }
                    )
                    continue

            # 符合要求的数据处理
            all_dir_info_data[one_folder] = value

        # 结合上述返回结果进行数据组合拼接
        # 返回可能存在的情况：1、存在文件夹不匹配数据，2、存在货号数据缺失
        goods_no_dict, error_folder_name_list = merge_local_and_remote_data(
            all_dir_info_data=all_dir_info_data, remote_data=remote_data
        )
        # 文件在系统中没有匹配的结果
        if error_folder_name_list:
            for one_folder in error_folder_name_list:
                error_folder_list.append(
                    {
                        "folder_name": one_folder,
                        "folder_path": "{}/{}".format(image_dir, one_folder),
                    }
                )
                return_data["message"] += "文件夹：{} 找不到对应数据\n".format(
                    one_folder
                )
                return_data["data"]["config_data"]["success_handler"].append(
                    {
                        "goods_art_no": one_folder,
                        "success": False,
                        "info": f"文件夹：{one_folder} 找不到对应数据",
                    }
                )

        print("===============goods_no_dict==================")
        if settings.IS_TEST:
            _text = json.dumps(goods_no_dict)
            print(goods_no_dict)
            create_folder("qt_test")
            with open("qt_test/goods_no_dict.txt", "w", encoding="utf-8") as file:
                file.write(_text)
        print("===============goods_no_dict==================")

        # ===================================是否齐色检查=============================================
        # 如为红蜻蜓企业则还需要检查同款下是否齐全;数据返回结果为款号列表
        error_data_dict = {}
        if is_check_color_is_all:
            if not is_use_excel:
                if settings.PROJECT == "红蜻蜓":
                    error_data_dict = (
                        self.data_mode_generate_detail.check_goods_is_not_deficiency(
                            goods_no_dict
                        )
                    )
            else:
                error_data_dict = self.data_mode_generate_detail.check_goods_is_not_deficiency_form_excel(
                    goods_no_dict, excel_path
                )

        if error_data_dict:
            print("----error_data_dict----")
            print(json.dumps(error_data_dict))

            # 款号反向映射;因为部分key键格式为KUM9999999
            _x = {}
            for i, v in goods_no_dict.items():
                _x[v["款号"]] = i

            for goods_no, value in error_data_dict.items():
                if goods_no in _x:
                    goods_no = _x[goods_no]
                if goods_no in goods_no_dict:
                    # =====移动到错误文件夹======
                    for _folder_name in [
                        x["文件夹名称"] for x in goods_no_dict[goods_no]["货号资料"]
                    ]:
                        error_folder_list.append(
                            {
                                "folder_name": _folder_name,
                                "folder_path": "{}\{}".format(image_dir, _folder_name),
                            }
                        )
                        return_data["message"] += "文件夹：{}；{}\n".format(
                            _folder_name, value["message"]
                        )
                    # 从 正确 款下面进行数据剔除
                    goods_no_dict.pop(goods_no)

        print("-----------------1goods_no_dict---------------")
        print(json.dumps(goods_no_dict, ensure_ascii=False))
        print("-----------------1goods_no_dict---------------")

        # 如果没有有效数据则进行退出
        if not goods_no_dict:
            return_data["message"] += "没有任何有效数据\n"
            return return_data

        # 校验无误的文件夹数据  goods_no_dict为最终有效数据
        for goods_no, value in goods_no_dict.items():
            return_data["data"]["succeed_folder_list"].extend(
                [x["文件夹名称"] for x in goods_no_dict[goods_no]["货号资料"]]
            )

        # 如果是表格数据，则获取表格数据中需要生成的货号
        # 数据结构
        # {“款号1”：
        # {“模板名称1”：data_dict1,
        # “模板名称2”：data_dict2,
        # }}

        if is_use_excel:
            excel_temp_goods_no_data = (
                self.data_mode_generate_detail.get_basic_template_information(
                    _goods_no_dict=goods_no_dict, excel_path=excel_path
                )
            )
        else:
            excel_temp_goods_no_data = {}

        print(
            "731===================excel_temp_goods_no_data,is_use_excel:{}".format(
                is_use_excel
            )
        )
        print(json.dumps(excel_temp_goods_no_data))

        # ===========数据组装，统计每个款需要生成哪些模板==============
        # 不适用表格指定模板
        goods_no_need_temps = {}
        # isUseTemplate 为false 表示使用excel表格数据
        if not is_use_excel:
            for i in goods_no_dict:
                goods_no_need_temps[i] = [temp_name]
        else:
            for i in goods_no_dict:
                # i 为款号
                if i in excel_temp_goods_no_data:
                    # 获取 某个款号的所有允许生成的模板列表
                    goods_no_need_temps[i] = list(excel_temp_goods_no_data[i].keys())

        # ========开始执行详情图生成===================
        # _goods_no_dict = goods_no_dict
        _goods_no_dict = {}

        # assigned_page_dict 如存在对应模板的，则不管是否有过滤都需要生成
        # 检查是否已存在模板，已存在的需要进行跳过；可能部分模板已存在，部分不存在。
        finally_goods_no_need_temps = {}
        for goods_no, value in goods_no_dict.items():
            if goods_no not in goods_no_need_temps:
                continue
            for __temp_name in goods_no_need_temps[goods_no]:
                _path = "{}/{}/{}/{}".format(
                    image_dir, "软件-详情图生成", __temp_name, goods_no
                )
                if not os.path.exists(_path):
                    print("款号详情图不存在", _path)
                    if goods_no not in finally_goods_no_need_temps:
                        finally_goods_no_need_temps[goods_no] = []
                        _goods_no_dict[goods_no] = value  # 需要生成的数据
                    finally_goods_no_need_temps[goods_no].append(__temp_name)
                else:
                    print("款号详情图存在", _path)
                    # 如果在指定模板中存在，则也需要生成
                    if __temp_name in assigned_page_dict:
                        print("指定模板需要更新", _path)
                        if goods_no not in finally_goods_no_need_temps:
                            finally_goods_no_need_temps[goods_no] = []
                            _goods_no_dict[goods_no] = value  # 需要生成的数据
                        finally_goods_no_need_temps[goods_no].append(__temp_name)
                    else:
                        # output/2025-04-03/软件-详情图生成/huilima-2/AQN141132
                        return_data["data"]["config_data"]["out_put_dir"] = _path
                        if detail_is_pass:
                            return_data[
                                "message"
                            ] += "\n款号：{}，模板：{} 已存在".format(
                                goods_no, __temp_name
                            )
                            return_data["data"]["config_data"][
                                "success_handler"
                            ].append(
                                {
                                    "goods_art_no": goods_no,
                                    "success": True,
                                    "info": "处理成功",
                                }
                            )
                        else:
                            if goods_no not in finally_goods_no_need_temps:
                                finally_goods_no_need_temps[goods_no] = []
                                _goods_no_dict[goods_no] = value  # 需要生成的数据
                            finally_goods_no_need_temps[goods_no].append(__temp_name)

            pass

        print("-----------------2goods_no_dict---------------")
        print(json.dumps(_goods_no_dict, ensure_ascii=False))
        print("-----------------2goods_no_dict---------------")
        return_data["data"]["error_folder_list"] = error_folder_list

        if len(_goods_no_dict) == 0:
            return_data["message"] += "\n没有任何文件夹需要执行"

        return_data["data"]["goods_no_dict"] = _goods_no_dict
        return_data["data"]["excel_temp_goods_no_data"] = excel_temp_goods_no_data
        return_data["data"]["finally_goods_no_need_temps"] = finally_goods_no_need_temps

        return_data["code"] = 0
        return return_data

    def move_error_folders(self, one_path, target_folder, message=""):
        if os.path.exists(one_path):
            check_path(target_folder)
            move_folders(path_list=[one_path], target_folder=target_folder)

    def check_for_detail_first_call_back(self, data):
        # 首次数据校验的信息返回
        # self.show_message(text="22222222222222222222222")
        # QMessageBox.critical(self, "警告", "1111111", QMessageBox.Ok)
        code = data["code"]
        config_data = data["data"]["config_data"]
        target_error_folder = config_data["target_error_folder"]
        print("635  check_for_detail_first_call_back")
        print(data)
        if code != 0:
            raise UnicornException(config_data["success_handler"])
        do_next = False
        if data["message"]:
            button_1, button_2, button_3 = None, None, None
            text = data["message"]
            if code == 0:
                if data["data"]:
                    if data["data"]["error_folder_list"]:
                        print("22----------error_folder_list------------")
                        print(json.dumps(data["data"]["error_folder_list"]))
                        button_2 = "移除错误文件"
                    if data["data"]["goods_no_dict"]:
                        if button_2:
                            button_1 = "移除并继续"
                            button_3 = "继续(忽略其他)"
                        else:
                            button_1 = "继续"
                    if data["data"]["succeed_folder_list"]:
                        text += "\n==================\n校验无误数据：{}个文件夹".format(
                            len(data["data"]["succeed_folder_list"])
                        )
            self.show_progress_detail(text=data["message"])
            if button_1 is None and button_2 is None and button_3 is None:
                pass
            elif button_1 == "继续" and button_2 is None and button_3 is None:
                do_next = True
            else:
                print("runmain  642----------------")
                # todo 弹框修改处理等
                _dialog_dict = {
                    "text": text,
                    "button_1": button_1,
                    "button_2": button_2,
                    "button_3": button_3,
                    "windows": self,
                }
                # self.show_dialog_sign.emit(_dialog_dict)
                # # 等待事件被设置
                # self.event.wait()
                print("self.dialog_result", self.dialog_result)

                # my_dialog = DialogShow(
                #     self.windows, text=text, button_1=button_1, button_2=button_2, button_3=button_3
                # )
                print("my_dialog.flag_name", self.dialog_result)
                if "移除" in self.dialog_result:
                    for error_folder_data in data["data"]["error_folder_list"]:
                        self.move_error_folders(
                            one_path=error_folder_data["folder_path"],
                            target_folder=target_error_folder,
                        )
                if "继续" in self.dialog_result:
                    do_next = True

        if data["data"]["goods_no_dict"] and not data["data"]["error_folder_list"]:
            do_next = True

        if do_next:
            # self.set_state(state_value=1)
            getAllData = data["data"]
            base_temp_name = getAllData["temp_name"]
            set_temp_name = getAllData.get("template_name", "")
            kwargs = {
                "config_data": config_data,
                "_goods_no_dict": data["data"]["goods_no_dict"],
                "temp_name": base_temp_name,
                "temp_name_list": data["data"]["temp_name_list"],
                "assigned_page_dict": data["data"]["assigned_page_dict"],
                "excel_temp_goods_no_data": data["data"]["excel_temp_goods_no_data"],
                # 表格数据可能存在多模板，数据结构为一个款号下的多个模板的数据列表
                "finally_goods_no_need_temps": data["data"][
                    "finally_goods_no_need_temps"
                ],  # 每个款号需要生成的模板数据
            }
            # todo work
            new_func = self.detail_run_by_thread(
                config_data=kwargs["config_data"],
                _goods_no_dict=kwargs["_goods_no_dict"],
                temp_name=kwargs["temp_name"],
                temp_name_list=kwargs["temp_name_list"],
                assigned_page_dict=kwargs["assigned_page_dict"],
                excel_temp_goods_no_data=kwargs["excel_temp_goods_no_data"],
                finally_goods_no_need_temps=kwargs["finally_goods_no_need_temps"],
            )
            # self._w_3 = WorkerOneThread(func=new_func, name="_w_3")
            # self._w_3.start()
            return new_func
            # threading.Thread(target=self.detail_run_by_thread, kwargs=kwargs).start()
        else:
            config_data["sign_text"] = "已结束详情处理"
            # self.run_end_sign.emit(config_data)
            return config_data

    def detail_run_by_thread(
        self,
        config_data,
        _goods_no_dict,
        temp_name,
        temp_name_list,
        assigned_page_dict,
        excel_temp_goods_no_data,
        finally_goods_no_need_temps,
    ):
        """
        excel_temp_goods_no_data: {},  # 表格数据可能存在多模板，数据结构为一个款号下的多个模板的数据列表
        finally_goods_no_need_temps: {},  # 每个款号需要生成的模板数据
        """

        # 开始处理
        self.n = 0
        self.total_num = len(_goods_no_dict)
        self.fail_num = 0
        is_use_excel = config_data["is_use_excel"]
        image_dir = config_data["image_dir"]

        # 详情图生成结果文件夹
        out_put_dir = "{}\软件-详情图生成".format(image_dir)
        if settings.IS_TEST:
            print("==============_goods_no_dict  打印=================")

            print(json.dumps(_goods_no_dict))

            print("==============_goods_no_dict  打印-end=================")

        all_detail_path_list = []
        out_put_dir_resp = ""
        for goods_no, temp_name_list in finally_goods_no_need_temps.items():
            for _temp_name in temp_name_list:
                try:
                    # if _temp_name != "xiaosushuoxie-4":
                    #     continue
                    assigned_page_list = []
                    if _temp_name in assigned_page_dict:
                        assigned_page_list = assigned_page_dict[_temp_name]
                    # 如果为使用表格，则获取表格中的数据作为款号的基础数据
                    temp_info_data = copy.copy(_goods_no_dict[goods_no])
                    if is_use_excel:
                        # 将表格中的数据进行替换
                        if goods_no in excel_temp_goods_no_data:
                            if _temp_name in excel_temp_goods_no_data[goods_no]:
                                # 将表格中的特定的模板的行，替换到goods_no的data中，因为不同的模板有数据特殊性
                                for _key, _key_value in excel_temp_goods_no_data[
                                    goods_no
                                ][_temp_name].items():
                                    if _key in temp_info_data:
                                        temp_info_data[_key] = _key_value
                    print("goods_no:{},_temp_name:{}".format(goods_no, _temp_name))
                    out_put_dir_resp = "{}/详情模板{}/{}".format(
                        out_put_dir, _temp_name, goods_no
                    )
                    all_detail_path_list.append(
                        "{}/详情模板{}/{}".format(out_put_dir, _temp_name, goods_no)
                    )
                    # continue
                    self.detail_deal_one_data(
                        goods_no=goods_no,
                        value=temp_info_data,
                        out_put_dir=out_put_dir,
                        temp_name=_temp_name,
                        assigned_page_list=assigned_page_list,
                        temp_class=config_data["temp_class"],
                        target_error_folder=config_data["target_error_folder"],
                        image_dir=config_data["image_dir"],
                    )
                    config_data["success_handler"].append(
                        {"goods_art_no": goods_no, "success": True, "info": "处理成功"}
                    )
                    recordDataPoint(
                        token=self.token,
                        uuid=self.uuid,
                        page="详情图生成成功",
                        data={"goods_art_no": goods_no, "temp_name": _temp_name},
                    )
                except BaseException as e:
                    self.show_progress_detail(
                        {
                            "goods_art_no": goods_no,
                            "success": False,
                            "info": "款：{}生成详情异常：{}".format(goods_no, e),
                        }
                    )
                    print(e)
                    # raise UnicornException("款：{}生成详情异常：{}".format(goods_no, e))
                    config_data["success_handler"].append(
                        {
                            "goods_art_no": goods_no,
                            "success": False,
                            "info": "款：{}生成详情异常：{}".format(goods_no, e),
                        }
                    )
                    recordDataPoint(
                        token=self.token,
                        uuid=self.uuid,
                        page="详情图生成失败",
                        data={
                            "goods_art_no": goods_no,
                            "temp_name": _temp_name,
                            "message": str(e),
                        },
                    )

        # ==============完成处理==============
        self.set_state(state_value=2)
        if self.total_num:
            if self.fail_num:
                self.show_progress_detail(
                    "处理完成,-----处理失败数据：{}个款".format(self.fail_num)
                )
            else:
                self.show_progress_detail("处理完成")
        else:
            self.show_progress_detail("没有任何数据")

        config_data["sign_text"] = "已结束详情处理"
        config_data["all_detail_path_list"] = all_detail_path_list
        config_data["out_put_dir"] = out_put_dir_resp
        print("out_put_dir_resp", out_put_dir_resp)
        # 打开文件夹
        # os.startfile(out_put_dir)

        return config_data

    def detail_run_by_thread11111(
        self,
        config_data,
        _goods_no_dict,
        temp_name,
        temp_name_list,
        assigned_page_dict,
        excel_temp_goods_no_data,
        finally_goods_no_need_temps,
    ):
        """
        excel_temp_goods_no_data: {},  # 表格数据可能存在多模板，数据结构为一个款号下的多个模板的数据列表
        finally_goods_no_need_temps: {},  # 每个款号需要生成的模板数据
        """

        # 开始处理
        self.n = 0
        self.total_num = len(_goods_no_dict)
        self.fail_num = 0
        is_use_excel = config_data["is_use_excel"]
        image_dir = config_data["image_dir"]

        # 详情图生成结果文件夹
        out_put_dir = "{}\软件-详情图生成".format(image_dir)
        if settings.IS_TEST:
            print("==============_goods_no_dict  打印=================")

            print(json.dumps(_goods_no_dict))

            print("==============_goods_no_dict  打印-end=================")

        if settings.IS_TEST:
            max_workers = 1
        else:
            max_workers = 1

        all_detail_path_list = []

        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
            futures = []
            for goods_no, temp_name_list in finally_goods_no_need_temps.items():
                for _temp_name in temp_name_list:
                    # if _temp_name != "xiaosushuoxie-4":
                    #     continue

                    assigned_page_list = []
                    if _temp_name in assigned_page_dict:
                        assigned_page_list = assigned_page_dict[_temp_name]
                    # 如果为使用表格，则获取表格中的数据作为款号的基础数据
                    temp_info_data = copy.copy(_goods_no_dict[goods_no])
                    if is_use_excel:
                        # 将表格中的数据进行替换
                        if goods_no in excel_temp_goods_no_data:
                            if _temp_name in excel_temp_goods_no_data[goods_no]:
                                # 将表格中的特定的模板的行，替换到goods_no的data中，因为不同的模板有数据特殊性
                                print("xxxxxx====>", excel_temp_goods_no_data[goods_no])
                                for _key, _key_value in excel_temp_goods_no_data[
                                    goods_no
                                ][_temp_name].items():
                                    if _key in temp_info_data:
                                        temp_info_data[_key] = _key_value

                    print("temp_info_data11111111111111111111111")
                    print("goods_no:{},_temp_name:{}".format(goods_no, _temp_name))
                    all_detail_path_list.append(
                        "{}/{}/".format(out_put_dir, _temp_name, goods_no)
                    )
                    # continue
                    futures.append(
                        executor.submit(
                            self.detail_deal_one_data,
                            goods_no=goods_no,
                            value=temp_info_data,
                            out_put_dir=out_put_dir,
                            temp_name=_temp_name,
                            assigned_page_list=assigned_page_list,
                        )
                    )

            # for goods_no, value in _goods_no_dict.items():
            #     _temp_name = temp_name
            #     # 使用自定义的表格数据
            #     if self.isUseTemplate is False:
            #         if "模板名称" in value:
            #             if value["模板名称"] in temp_name_list:
            #                 _temp_name = value["模板名称"]
            #     assigned_page_list = []
            #     if _temp_name in assigned_page_dict:
            #         assigned_page_list = assigned_page_dict[_temp_name]
            #
            #     futures.append(executor.submit(
            #         self.deal_one_data,
            #         goods_no=goods_no,
            #         value=value,
            #         out_put_dir=out_put_dir,
            #         temp_name=_temp_name,
            #         assigned_page_list=assigned_page_list,
            #     ))

            # 使用 wait 方法等待所有任务完成
            done, not_done = concurrent.futures.wait(futures)

            # 处理完成的任务
            for future in done:
                if settings.IS_TEST:
                    result = future.result()

        # ==============完成处理==============
        self.set_state(state_value=2)
        if self.total_num:
            if self.fail_num:
                self.show_progress_detail(
                    "处理完成,-----------处理失败数据：{}个款".format(self.fail_num)
                )
            else:
                self.show_progress_detail("处理完成")
        else:
            self.show_progress_detail("没有任何数据")

        config_data["sign_text"] = "已结束详情处理"
        config_data["all_detail_path_list"] = all_detail_path_list
        self.run_end_sign.emit(config_data)

    def show_progress_detail(self, text):
        # self.show_progress_detail_sign.emit(text)
        # self.windows.show_progress_detail(text)
        print("text=====>", text)
        return text

    def detail_deal_one_data(
        self,
        goods_no,
        value,
        out_put_dir,
        temp_name,
        assigned_page_list,
        temp_class,
        target_error_folder,
        image_dir,
    ):
        # if self.windows.state == 99:
        #     self.show_progress_detail("用户主动取消：{}".format(goods_no))
        #     return
        self.show_progress_detail("正在生成：{}，模板：{}".format(goods_no, temp_name))
        is_deal_success = False
        print("=================deal_one_data=====================")
        print("goods_no", goods_no)
        print("模板：", temp_name)
        print("value：", value)
        print("temp_class:", temp_class)
        if settings.IS_TEST:
            temp_class[temp_name](
                goods_no,
                value,
                out_put_dir=out_put_dir,
                windows=self.windows,
                assigned_page_list=assigned_page_list,
            )
            is_deal_success = True
        else:
            try:
                # # 处理图片详情图生成
                temp_class[temp_name](
                    goods_no,
                    value,
                    out_put_dir=out_put_dir,
                    windows=self.windows,
                    assigned_page_list=assigned_page_list,
                )
                is_deal_success = True
            except BaseException as e:
                self.show_progress_detail("{}处理失败".format(goods_no))
                error_text = "{}".format(e)
                if "Unable to allocate" in error_text:
                    error_text = "电脑内存不足，生成失败"
                print(
                    f"发生错误的文件: {e.__traceback__.tb_frame.f_globals['__file__']}"
                )
                print(f"发生错误的行号: {e.__traceback__.tb_lineno}")
                # self.show_progress_detail("失败原因：{}".format(error_text))
                self.fail_num += 1
                raise UnicornException(
                    "{}处理失败,失败原因：{}".format(goods_no, error_text)
                )

        self.n += 1

        if not is_deal_success:
            goods_art_no_list = value["货号资料"]
            self.show_progress_detail("处理失败")
            self.show_progress_detail(
                "相关货号：{}".format([x["货号"] for x in goods_art_no_list])
            )
            # 将相关的文件夹统一移动至错误文件夹
            move_folders(
                path_list=[
                    "{}/{}".format(image_dir, x)
                    for x in [x["文件夹名称"] for x in goods_art_no_list]
                ],
                target_folder=target_error_folder,
            )
            pass
        # 更新进度
        print("更新进度============>", self.n, self.total_num)
        # self.windows.progress_sign.emit(
        #     {
        #         "type": "详情图生成",
        #         "progress_bar_value": int(self.n / self.total_num * 100),
        #     }
        # )

    def check_serializable(self, obj):  # 检查某个对象其中的属性哪些不能被序列化
        for attr_name in dir(obj):
            if not attr_name.startswith("__"):
                try:
                    attr_value = getattr(obj, attr_name)
                    serialized = pickle.dumps(attr_value)
                    print(f"属性 {attr_name} 是可序列化的。")
                except (TypeError, pickle.PicklingError):
                    print(f"属性 {attr_name} 不可序列化。")

    def on_dialog_result(self, result):
        """处理对话框结果"""
        self.dialog_result = result
        print("972  处理对话框结果:{}".format(result))
        # self.quit()  # 结束事件循
        self.event.set()
