import os
import copy
import time

from .image_deal_base_func import *
from PIL import Image, ImageDraw
from blend_modes import multiply
import os
import settings
from functools import wraps
from .multi_threaded_image_saving import ImageSaver
from .get_mask_by_green import GetMask
from middleware import UnicornException

def time_it(func):
    @wraps(func)  # 使用wraps来保留原始函数的元数据信息
    def wrapper(*args, **kwargs):
        start_time = time.time()  # 记录开始时间
        result = func(*args, **kwargs)  # 调用原始函数
        end_time = time.time()  # 记录结束时间
        print(
            f"Executing {func.__name__} took {end_time - start_time:.4f} seconds."
        )  # 打印耗时
        return result

    return wrapper


class GeneratePic(object):
    def __init__(self, is_test=False):
        # self.logger = MyLogger()
        self.is_test = is_test
        self.saver = ImageSaver()
        pass

    @time_it
    def get_mask_and_config(self, im_jpg: Image, im_png: Image, curve_mask: bool):
        """
        步骤：
        1、尺寸进行对应缩小
        2、查找并设定鞋底阴影蒙版
        3、自动色阶检查亮度
        4、输出自动色阶参数、以及放大的尺寸蒙版
        """
        # ===================尺寸进行对应缩小（提升处理速度）
        im_jpg = to_resize(im_jpg, width=800)
        im_png = to_resize(im_png, width=800)
        x1, y1, x2, y2 = im_png.getbbox()

        cv2_png = pil_to_cv2(im_png)
        # =====================设定鞋底阴影图的蒙版
        # 查找每列的最低非透明点
        min_y_values = find_lowest_non_transparent_points(cv2_png)
        # 在鞋底最低处增加一条直线蒙版，蒙版宽度为有效区域大小
        image_high = im_jpg.height
        print("图片高度：", image_high)
        cv2_jpg = pil_to_cv2(im_jpg)

        # 返回线条图片，以及最低位置
        print("返回线条图片，以及最低位置")
        # crop_image_box=(x1, y1, x2, y2),
        if curve_mask:
            crop_image_box = None
        else:
            # 不需要曲线部分的蒙版
            crop_image_box = (x1, y1, x2, y2)
        img_with_shifted_line, lowest_y = draw_shifted_line(
            image=cv2_jpg,
            min_y_values=min_y_values,
            shift_amount=15,
            one_line_pos=(x1, x2),
            line_color=(0, 0, 0),
            line_thickness=20,
            app=None,
            crop_image_box=crop_image_box,
        )
        print("66  制作蒙版")
        # 制作蒙版
        mask_line = cv2_to_pil(img_with_shifted_line)
        mask = mask_line.convert("L")  # 转换为灰度图
        mask = ImageOps.invert(mask)
        # 蒙版扩边
        print("72  蒙版扩边")
        # 默认expansion_radius 65 blur_radius 45
        mask = expand_or_shrink_mask(
            pil_image=mask, expansion_radius=50, blur_radius=35
        )

        # =============使用绿色蒙版进行处理
        if settings.IS_GET_GREEN_MASK:
            print("============使用绿色蒙版进行处理")
            mask = mask.convert("RGB")
            white_bg = Image.new(mode="RGB", size=im_png.size, color=(0, 0, 0))
            green_areas_mask_pil = GetMask().find_green_areas(cv2_jpg)
            green_areas_mask_pil = expand_or_shrink_mask(
                pil_image=green_areas_mask_pil, expansion_radius=15, blur_radius=5
            )
            mask.paste(white_bg, mask=green_areas_mask_pil.convert("L"))
            mask = mask.convert("L")

        # ====================生成新的图片
        print("84  生成新的图片")
        bg = Image.new(mode="RGBA", size=im_png.size, color=(255, 255, 255, 255))
        bg.paste(im_png, mask=im_png)
        bg.paste(im_jpg, mask=mask)  # 粘贴有阴影的地方
        if image_high > y2 + 20:
            lowest_y = y2 + 20
        if self.is_test:
            _bg = bg.copy()
            draw = ImageDraw.Draw(_bg)
            # 定义直线的起点和终点坐标
            start_point = (0, lowest_y)  # 直线的起始点
            end_point = (_bg.width, lowest_y)  # 直线的结束点
            # 定义直线的颜色（R, G, B）
            line_color = (255, 0, 0)  # 红色
            _r = Image.new(mode="RGBA", size=im_png.size, color=(246, 147, 100, 255))
            # mask_line = mask_line.convert('L')  # 转换为灰度图
            # mask_line = ImageOps.invert(mask_line)
            # _bg.paste(_r, mask=mask)
            # 绘制直线
            draw.line([start_point, end_point], fill=line_color, width=1)
            _bg.show()

        # bg.save(r"C:\Users\gymmc\Desktop\data\bg.png")
        # bg.show()
        # ==================自动色阶处理======================
        # 对上述拼接后的图片进行自动色阶处理
        bg = bg.convert("RGB")
        _im = cv2.cvtColor(np.asarray(bg), cv2.COLOR_RGB2BGR)
        # 背景阴影
        im_shadow = cv2.cvtColor(_im, cv2.COLOR_BGR2GRAY)
        print("image_high lowest_y", image_high, lowest_y)
        if lowest_y < 0 or lowest_y >= image_high:
            lowest_y = image_high - 1
        print("image_high lowest_y", image_high, lowest_y)
        rows = [lowest_y]  # 需要检查的像素行

        print("copy.copy(im_shadow)")
        _im_shadow = copy.copy(im_shadow)
        Midtones = 0.7
        Highlight = 235
        k = copy.copy(settings.COLOR_GRADATION_CYCLES)
        print("循环识别")
        xunhuan = 0
        while k:
            xunhuan += 1
            # if settings.app:
            #     settings.app.processEvents()
            k -= 1
            Midtones += 0.035
            if Midtones > 1.7:
                Midtones = 1.7
            Highlight -= 3

            _im_shadow = levels_adjust(
                img=im_shadow,
                Shadow=0,
                Midtones=Midtones,
                Highlight=Highlight,
                OutShadow=0,
                OutHighlight=255,
                Dim=3,
            )
            brightness_list = calculate_average_brightness_opencv(
                img_gray=_im_shadow, rows_to_check=rows
            )
            print(
                "循环识别:{},Midtones:{},Highlight:{},brightness_list:{}".format(
                    xunhuan, Midtones, Highlight, brightness_list
                )
            )
            if brightness_list[0] >= settings.GRENERATE_MAIN_PIC_BRIGHTNESS:
                break

        im_shadow = cv2_to_pil(_im_shadow)

        # ========================================================
        # 计算阴影的亮度，用于确保阴影不要太黑

        # 1、图片预处理，只保留阴影
        only_shadow_img = im_shadow.copy()
        only_shadow_img.paste(
            Image.new(
                mode="RGBA", size=only_shadow_img.size, color=(255, 255, 255, 255)
            ),
            mask=im_png,
        )
        average_brightness = calculated_shadow_brightness(only_shadow_img)
        print("average_brightness:", average_brightness)

        config = {
            "Midtones": Midtones,
            "Highlight": Highlight,
            "average_brightness": average_brightness,
        }

        return mask, config

    def get_mask_and_config_1_2025_05_18(self, im_jpg: Image, im_png: Image):
        """
        步骤：
        1、尺寸进行对应缩小
        2、查找并设定鞋底阴影蒙版
        3、自动色阶检查亮度
        4、输出自动色阶参数、以及放大的尺寸蒙版
        """
        # ===================尺寸进行对应缩小（提升处理速度）
        im_jpg = to_resize(im_jpg, width=800)
        im_png = to_resize(im_png, width=800)
        x1, y1, x2, y2 = im_png.getbbox()

        cv2_png = pil_to_cv2(im_png)
        # =====================设定鞋底阴影图的蒙版
        # 查找每列的最低非透明点
        min_y_values = find_lowest_non_transparent_points(cv2_png)
        # 在鞋底最低处增加一条直线蒙版，蒙版宽度为有效区域大小
        image_high = im_jpg.height
        print("图片高度：", image_high)
        cv2_jpg = pil_to_cv2(im_jpg)
        # 返回线条图片，以及最低位置
        print("返回线条图片，以及最低位置")
        img_with_shifted_line, lowest_y = draw_shifted_line(
            image=cv2_jpg,
            min_y_values=min_y_values,
            shift_amount=15,
            one_line_pos=(x1, x2),
            line_color=(0, 0, 0),
            line_thickness=20,
            app=None,
            crop_image_box=(x1, y1, x2, y2),
        )
        print("66  制作蒙版")
        # 制作蒙版
        mask_line = cv2_to_pil(img_with_shifted_line)
        mask = mask_line.convert("L")  # 转换为灰度图
        mask = ImageOps.invert(mask)
        # 蒙版扩边
        print("72  蒙版扩边")
        # 默认expansion_radius 65 blur_radius 45
        mask = expand_or_shrink_mask(
            pil_image=mask, expansion_radius=50, blur_radius=35
        )

        # mask1 = expand_mask(mask, expansion_radius=30, blur_radius=10)
        # mask1.save("mask1.png")
        # mask2 = expand_or_shrink_mask(pil_image=mask, expansion_radius=60, blur_radius=30)
        # mask2.save("mask2.png")
        # raise 11

        # ====================生成新的图片
        print("84  生成新的图片")
        bg = Image.new(mode="RGBA", size=im_png.size, color=(255, 255, 255, 255))
        bg.paste(im_png, mask=im_png)
        bg.paste(im_jpg, mask=mask)  # 粘贴有阴影的地方
        if self.is_test:
            _bg = bg.copy()
            draw = ImageDraw.Draw(_bg)
            # 定义直线的起点和终点坐标
            start_point = (0, lowest_y)  # 直线的起始点
            end_point = (_bg.width, lowest_y)  # 直线的结束点
            # 定义直线的颜色（R, G, B）
            line_color = (255, 0, 0)  # 红色
            # 绘制直线
            draw.line([start_point, end_point], fill=line_color, width=1)
            # mask.show()
            # bg = pil_to_cv2(bg)
            # cv2.line(bg, (x1, lowest_y + 5), (x2, lowest_y + 5), color=(0, 0, 0),thickness=2)
            # bg = cv2_to_pil(bg)
            _r = Image.new(mode="RGBA", size=im_png.size, color=(246, 147, 100, 255))
            mask_line = mask_line.convert("L")  # 转换为灰度图
            mask_line = ImageOps.invert(mask_line)
            _bg.paste(_r, mask=mask)
            _bg.show()

        # bg.save(r"C:\Users\gymmc\Desktop\data\bg.png")
        # bg.show()
        # ==================自动色阶处理======================
        # 对上述拼接后的图片进行自动色阶处理
        bg = bg.convert("RGB")
        _im = cv2.cvtColor(np.asarray(bg), cv2.COLOR_RGB2BGR)
        # 背景阴影
        im_shadow = cv2.cvtColor(_im, cv2.COLOR_BGR2GRAY)
        print("image_high lowest_y", image_high, lowest_y)
        if lowest_y < 0 or lowest_y >= image_high:
            lowest_y = image_high - 1
        print("image_high lowest_y", image_high, lowest_y)
        rows = [lowest_y]  # 需要检查的像素行

        print("copy.copy(im_shadow)")
        _im_shadow = copy.copy(im_shadow)
        Midtones = 0.7
        Highlight = 235
        k = 12
        print("循环识别")
        while k:
            print("循环识别：{}".format(k))
            # if settings.app:
            #     settings.app.processEvents()
            k -= 1
            Midtones += 0.1
            if Midtones > 1:
                Midtones = 1
            Highlight -= 3
            _im_shadow = levels_adjust(
                img=im_shadow,
                Shadow=0,
                Midtones=Midtones,
                Highlight=Highlight,
                OutShadow=0,
                OutHighlight=255,
                Dim=3,
            )
            brightness_list = calculate_average_brightness_opencv(
                img_gray=_im_shadow, rows_to_check=rows
            )
            print(brightness_list)
            if brightness_list[0] >= settings.GRENERATE_MAIN_PIC_BRIGHTNESS:
                break
        print("Midtones,Highlight:", Midtones, Highlight)

        im_shadow = cv2_to_pil(_im_shadow)

        # ========================================================
        # 计算阴影的亮度，用于确保阴影不要太黑

        # 1、图片预处理，只保留阴影
        only_shadow_img = im_shadow.copy()
        only_shadow_img.paste(
            Image.new(
                mode="RGBA", size=only_shadow_img.size, color=(255, 255, 255, 255)
            ),
            mask=im_png,
        )
        average_brightness = calculated_shadow_brightness(only_shadow_img)
        print("average_brightness:", average_brightness)

        config = {
            "Midtones": Midtones,
            "Highlight": Highlight,
            "average_brightness": average_brightness,
        }

        return mask, config

    def my_test(self, **kwargs):
        if "output_queue" in kwargs:
            output_queue = kwargs["output_queue"]
        else:
            output_queue = None
        time.sleep(3)
        if output_queue is not None:
            output_queue.put(True)

    @time_it
    def run(
        self,
        image_path,
        cut_image_path,
        out_path,
        image_deal_mode=0,
        image_index=99,
        out_pic_size=1024,
        is_logo=True,
        out_process_path_1=None,
        out_process_path_2=None,
        resize_mode=None,
        max_box=None,
        logo_path="",
        curve_mask=False,
        **kwargs,
    ):  # im 为cv对象
        """
        image_path:原始图
        cut_image_path:抠图结果 与原始图尺寸相同
        out_path:输出主图路径
        image_deal_mode:图片处理模式，1表示需要镜像处理
        image_index：图片顺序索引
        out_pic_size：输出图片宽度大小
        is_logo=True 是否要添加logo水印
        out_process_path_1=None, 有阴影的图片，白底非透明
        out_process_path_2=None, 已抠图的图片
        resize_mode=0,1,2 主体缩小尺寸
        curve_mask 为True时，表示为对鞋曲线部分的mask，不做剪裁
        """
        if "output_queue" in kwargs:
            output_queue = kwargs["output_queue"]
        else:
            output_queue = None

        # ==========先进行剪切原图
        _s = time.time()
        orign_im = Image.open(image_path)  # 原始图
        print("242  need_time_1:{}".format(time.time() - _s))

        orign_x, orign_y = orign_im.size
        cut_image = Image.open(cut_image_path)  # 原始图的已扣图
        cut_image, new_box = get_mini_crop_img(img=cut_image)
        im_shadow = orign_im.crop(new_box)  # 切图
        new_x, new_y = im_shadow.size

        # ================自动色阶处理
        _s = time.time()
        shadow_mask, config = self.get_mask_and_config(
            im_jpg=im_shadow, im_png=cut_image, curve_mask=curve_mask
        )
        print("242  need_time_2:{}".format(time.time() - _s))

        shadow_mask = shadow_mask.resize(im_shadow.size)

        # =====抠图，形成新的阴影背景图=====

        _new_im_shadow = Image.new(
            mode="RGBA", size=im_shadow.size, color=(255, 255, 255, 255)
        )
        _new_im_shadow.paste(im_shadow, mask=shadow_mask)  # 粘贴有阴影的地方
        # _new_im_shadow.show()
        _new_im_shadow = pil_to_cv2(_new_im_shadow)
        _new_im_shadow = cv2.cvtColor(_new_im_shadow, cv2.COLOR_BGR2GRAY)
        _new_im_shadow = levels_adjust(
            img=_new_im_shadow,
            Shadow=0,
            Midtones=config["Midtones"],
            Highlight=config["Highlight"],
            OutShadow=0,
            OutHighlight=255,
            Dim=3,
        )

        im_shadow = cv2_to_pil(_new_im_shadow)

        # ================处理阴影的亮度==================
        average_brightness = config["average_brightness"]
        if config["average_brightness"] < 180:
            # 调整阴影亮度
            backdrop_prepped = np.asfarray(
                Image.new(mode="RGBA", size=im_shadow.size, color=(255, 255, 255, 255))
            )
            im_shadow = im_shadow.convert("RGBA")
            source_prepped = np.asfarray(im_shadow)
            # im_shadow.show()

            opacity = (average_brightness - 30) / 160
            opacity = max(0.5, min(opacity, 1))

            print("阴影透明度：{}%".format(int(opacity * 100)))
            blended_np = multiply(
                backdrop_prepped, source_prepped, opacity=int(opacity * 100) / 100
            )
            im_shadow = Image.fromarray(np.uint8(blended_np)).convert("RGB")
            # im_shadow.show()

        # 把原图粘贴回去，避免色差
        im_shadow.paste(cut_image, (0, 0), mask=cut_image)
        # _new_im_shadow.show()

        # ===========处理其他====================

        # 保存带有阴影的底图，没有logo
        if out_process_path_1:
            out_image_1 = im_shadow.copy()
            if image_deal_mode == 1:
                out_image_1 = out_image_1.transpose(Image.FLIP_LEFT_RIGHT)

            self.saver.save_image(
                image=out_image_1, file_path=out_process_path_1, save_mode="png"
            )
            # save_image_by_thread(image=out_image_1, out_path=out_process_path_1)
            # out_image_1.save(out_process_path_1)

        # 保存抠图结果，没有底图，没有logo
        if out_process_path_2:
            out_image_2 = cut_image.copy()
            if image_deal_mode == 1:
                out_image_2 = out_image_2.transpose(Image.FLIP_LEFT_RIGHT)

            self.saver.save_image(
                image=out_image_2, file_path=out_process_path_2, save_mode="png"
            )
            # save_image_by_thread(image=out_image_2, out_path=out_process_path_2, save_mode="png")
            # out_image_2.save(out_process_path_2)

        # 不生成主图时直接退出
        if not out_path:
            return True

        # im_shadow.show()
        # =====================主图物体的缩放依据大小
        if max_box:
            im_shadow = to_resize(_im=im_shadow, width=max_box[0], high=max_box[1])
            cut_image = to_resize(_im=cut_image, width=max_box[0], high=max_box[1])
        else:
            if resize_mode is None:
                im_shadow = to_resize(_im=im_shadow, width=1400, high=1400)
                cut_image = to_resize(_im=cut_image, width=1400, high=1400)

            elif resize_mode == 1:
                im_shadow = to_resize(_im=im_shadow, width=1400, high=1400)
                cut_image = to_resize(_im=cut_image, width=1400, high=1400)

            elif resize_mode == 2:
                # todo 兼容长筒靴等，将图片大小限制在一个指定的box内
                im_shadow = to_resize(_im=im_shadow, width=650)
                cut_image = to_resize(_im=cut_image, width=650)
                # 再次检查需要约束缩小到一定高度，适应长筒靴
                _im_x, _im_y = cut_image.size
                if _im_y > 1400:
                    im_shadow = to_resize(_im=im_shadow, high=1400)
                    cut_image = to_resize(_im=cut_image, high=1400)

                # if im_shadow.height <= im_shadow.width * 1.2:
                #     im_shadow = to_resize(_im=im_shadow, width=650)
                #     cut_image = to_resize(_im=cut_image, width=650)
                # else:
                #     im_shadow = to_resize(_im=im_shadow, high=1400)
                #     cut_image = to_resize(_im=cut_image, high=1400)

        if image_deal_mode == 1:
            # 翻转
            im_shadow = im_shadow.transpose(Image.FLIP_LEFT_RIGHT)
            cut_image = cut_image.transpose(Image.FLIP_LEFT_RIGHT)

        # 创建底层背景
        image_bg = Image.new("RGB", (1600, 1600), (255, 255, 255))

        image_bg_x, image_bg_y = image_bg.size
        image_x, image_y = im_shadow.size

        _x = int((image_bg_x - image_x) / 2)
        _y = int((image_bg_y - image_y) / 2)

        image_bg.paste(im_shadow, (_x, _y))
        image_bg.paste(cut_image, (_x, _y), cut_image)  # 再叠加原图避免色差

        if "小苏" in settings.Company:
            # 所有主图加logo
            is_logo = True

        if is_logo:
            # logo_path = ""
            # if settings.PROJECT == "红蜻蜓":
            #     logo_path = r"resources\LOGO\HQT\logo.png"
            # elif settings.PROJECT == "惠利玛":
            #     if "小苏" in settings.Company:
            #         logo_path = r"resources\LOGO\xiaosushuoxie\logo.png"
            #     elif "惠利玛" in settings.Company:
            #         logo_path = r"resources\LOGO\HLM\logo.png"
            #     else:
            #         pass
            if not logo_path:
                logo_im = Image.new("RGBA", (1600, 1600), (0, 0, 0, 0))
            else:
                if os.path.exists(logo_path):
                    logo_im = Image.open(logo_path)
                    if logo_im.mode != 'RGBA':
                        logo_im = logo_im.convert('RGBA')
                else:
                    logo_im = Image.new("RGBA", (1600, 1600), (0, 0, 0, 0))

            try:
                image_bg.paste(logo_im, (0, 0), logo_im)
            except Exception as e:
                alpha_mask = logo_im.split()[3]
                image_bg.paste(logo_im, (0, 0), alpha_mask)
        out_pci_factor = float(
            1
            if settings.getSysConfigs("basic_configs", "image_sharpening", "1") == ""
            else settings.getSysConfigs("basic_configs", "image_sharpening", "1")
        )
        # image_bg = image_bg.resize((out_pic_size, out_pic_size), Image.BICUBIC)
        if out_pci_factor > 1.0:
            print("图片锐化处理")
            image_bg = sharpen_image(image_bg, factor=out_pci_factor)
        out_pci_mode = "." + settings.getSysConfigs(
            "basic_configs", "image_out_format", "png"
        )
        for imageSize in out_pic_size:
            dot_index = out_path.rfind(".")
            if dot_index != -1:
                # 拆分文件路径和后缀
                file_without_suffix = out_path[:dot_index]
                suffix = out_path[dot_index + 1 :]
            else:
                file_without_suffix = out_path
                suffix = ""
            # 单独拼接字符串示例
            new_file_path = f"{file_without_suffix}_{imageSize}.{suffix}"
            if imageSize < 1600:
                image_bg = image_bg.resize(
                    (imageSize, imageSize), resample=settings.RESIZE_IMAGE_MODE
                )
                if out_pci_mode == ".jpg":
                    self.saver.save_image(
                        image=image_bg,
                        file_path=new_file_path,
                        save_mode="jpg",
                        quality=None,
                        dpi=None,
                        _format="JPEG",
                    )
                    # save_image_by_thread(image_bg, out_path, save_mode="jpg", quality=None, dpi=None, _format="JPEG")
                    # image_bg.save(out_path, format="JPEG")
                elif out_pci_mode == ".png":
                    self.saver.save_image(
                        image=image_bg,
                        file_path=new_file_path,
                        save_mode="jpg",
                        quality=100,
                        dpi=(300, 300),
                        _format="JPEG",
                    )
                else:
                    new_format = out_pci_mode.split(".")[-1]
                    self.saver.save_image(
                        image=image_bg,
                        file_path=new_file_path,
                        save_mode=new_format,
                        quality=100,
                        dpi=(300, 300),
                        _format=new_format,
                    )
                    # save_image_by_thread(image_bg, out_path, save_mode="jpg", quality=100, dpi=(300, 300), _format="JPEG")
                    # image_bg.save(out_path, quality=100, dpi=(300, 300), format="JPEG")
            else:
                new_format = out_pci_mode.split(".")[-1]
                self.saver.save_image(
                    image=image_bg,
                    file_path=new_file_path,
                    save_mode=new_format,
                    _format=new_format,
                )
                # image_bg.save(out_path)

        if output_queue is not None:
            output_queue.put(True)
        return True
