import cv2
import os
import numpy as np
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
import json
import random
import traceback

class PosterInfo:
    def __init__(self, index, main_title, texts):
        self.index = index
        self.main_title = main_title
        self.texts = texts

class PosterConfig:
    def __init__(self, config_path):
        self.config_path = config_path
        try:
            if isinstance(config_path, str) and os.path.exists(config_path):
                # 如果是文件路径，从文件读取
                print(f"从文件加载配置: {config_path}")
                self.config = json.load(open(config_path, "r", encoding="utf-8"))
            else:
                # 如果是字符串但不是文件路径，尝试直接解析
                print("尝试直接解析配置字符串")
                self.config = json.loads(config_path)
            
            self.img_list = []
            for item in self.config:
                print(item)
                self.img_list.append([item['index'], item["main_title"], item["texts"]])
                # self.img_list.append(PosterInfo(item['img_url'], item['main_title'], item['texts']))
        except json.JSONDecodeError as e:
            print(f"JSON解析错误: {e}")
            print(f"尝试解析的内容: {config_path[:100]}...")  # 只打印前100个字符
            # 创建一个默认配置，使用空字符串
            self.config = [{"index": 0, "main_title": "", "texts": ["", ""]}]
            self.img_list = [[0, "", ["", ""]]]
            print("使用默认的空配置")
        except Exception as e:
            print(f"加载配置时出错: {e}")
            # 创建一个默认配置，使用空字符串
            self.config = [{"index": 0, "main_title": "", "texts": ["", ""]}]
            self.img_list = [[0, "", ["", ""]]]
            print("使用默认的空配置")
    
    def get_config(self):
        return self.config
    
    def get_config_by_index(self, index):
        if index >= len(self.config):
            print(f"警告: 索引 {index} 超出配置范围，使用默认配置")
            return self.config[0]
        return self.config[index]

class PosterGenerator:
    def __init__(self, base_dir, output_dir=None):
        # 基础路径设置
        if not base_dir or not os.path.isdir(base_dir):
            # Handle error: Base directory is essential
            raise ValueError(f"Poster assets base directory '{base_dir}' is invalid or not provided.")
        self.base_dir = base_dir
        print(f"Initializing PosterGenerator with asset base: {self.base_dir}") # Log the used base_dir
        self.font_dir = os.path.join(self.base_dir, "font")
        self.frame_dir = os.path.join(self.base_dir, "frames")  # 边框素材目录
        self.sticker_dir = os.path.join(self.base_dir, "stickers")  # 贴纸素材目录
        self.text_bg_dir = os.path.join(self.base_dir, "text_backgrounds")  # 文本框底图目录
       
        self.img_frame_posbility = 0.7
        self.text_bg_posbility = 0
        # 设置输出目录
        if output_dir:
            self.output_dir = output_dir
        else:
            self.output_dir = os.path.join(self.base_dir, "output")
        
        # 初始化资源
        self.fonts = self._initialize_fonts()
        self.frames = self._initialize_frames()
        self.stickers = self._initialize_stickers()
        self.text_bgs = self._initialize_text_backgrounds()
        
        # 创建输出目录
        os.makedirs(self.output_dir, exist_ok=True)
        
        # 固定使用白色字体蓝色描边效果
        self.selected_effect = "白色字体蓝色描边"
        
        # 海报计数器，用于控制添加边框的频率
        self.poster_count = 0
        self.default_font_path = os.path.join(self.font_dir, "华康海报体简.ttc")
        
    def _initialize_text_backgrounds(self):
        """初始化文本框底图"""
        try:
            text_bg_files = [f for f in os.listdir(self.text_bg_dir) if f.endswith(('.png'))]
            print(f"找到文本框底图: {text_bg_files}")
            return text_bg_files
        except Exception as e:
            print(f"初始化文本框底图失败: {e}")
            return []

    def _initialize_fonts(self):
        """初始化字体"""
        fonts = []
        try:
            font_files = [f for f in os.listdir(self.font_dir) if f.endswith(('.ttf', '.otf'))]
            print(f"找到字体文件: {font_files}")
            return font_files
        except Exception as e:
            print(f"初始化字体失败: {e}")
            return []

    def _initialize_frames(self):
        """初始化边框素材"""
        frames = []
        try:
            frame_files = [f for f in os.listdir(self.frame_dir) if f.endswith(('.png', '.jpg'))]
            print(f"找到边框素材: {len(frame_files)}个")
            return frame_files
        except Exception as e:
            print(f"初始化边框失败: {e}")
            return []

    def _initialize_stickers(self):
        """初始化贴纸素材"""
        stickers = []
        try:
            sticker_files = [f for f in os.listdir(self.sticker_dir) if f.endswith(('.png'))]
            print(f"找到贴纸素材: {sticker_files}")
            return sticker_files
        except Exception as e:
            print(f"初始化贴纸失败: {e}")
            return []

    def get_random_font(self):
        """获取随机字体"""
        try:
            # 使用正确的字体目录
            font_dir = self.font_dir
            
            # 获取所有支持的字体文件
            font_files = [f for f in os.listdir(font_dir) 
                         if f.lower().endswith(('.ttf', '.otf', '.ttc', '.TTC', '.TTF', '.OTF'))]
            
            if not font_files:
                print("警告: 字体目录为空，使用默认字体")
                return os.path.join(font_dir, "华康海报体简.ttc")
            
            # 随机选择一个字体文件
            font_file = random.choice(font_files)
            font_path = os.path.join(font_dir, font_file)
            
            # 验证字体文件是否存在且可读
            if not os.path.isfile(font_path):
                print(f"警告: 字体文件 {font_file} 不存在，使用默认字体")
                return os.path.join(font_dir, "华康海报体简.ttc")
            
            print(f"使用字体: {font_file}")
            return font_path
            
        except Exception as e:
            print(f"获取字体时出错: {str(e)}")
            return os.path.join(font_dir, "华康海报体简.ttc")

    def create_base_layer(self, image_path, target_size):
        """创建底层（图片层）
        
        Args:
            image_path: 可以是图片文件路径字符串，也可以是已加载的 PIL Image 对象
            target_size: 目标图片尺寸 (width, height)
            
        Returns:
            调整大小后的 PIL Image 对象
        """
        try:
            # 检查输入类型
            if isinstance(image_path, Image.Image):
                # 如果已经是 PIL Image 对象
                print("输入已是 PIL Image 对象，无需加载")
                base_image = image_path.convert('RGBA')
                print(f"图像原始尺寸: {base_image.size}")
            else:
                # 否则，作为路径处理
                # 先验证图片路径
                if not image_path:
                    raise ValueError("图片路径为空")
                    
                if not os.path.exists(image_path):
                    raise FileNotFoundError(f"图片文件不存在: {image_path}")
                    
                print(f"尝试加载底图: {image_path}")
                base_image = Image.open(image_path).convert('RGBA')
                print(f"底图加载成功，原始尺寸: {base_image.size}")
            
            # 调整尺寸
            base_image = base_image.resize(target_size, Image.Resampling.LANCZOS)
            print(f"底图调整尺寸完成: {target_size}")
            
            return base_image
        except FileNotFoundError as e:
            print(f"创建底层失败: {e}")
            print(f"当前工作目录: {os.getcwd()}")
            return Image.new('RGBA', target_size, (255, 255, 255, 255))
        except Exception as e:
            print(f"创建底层失败: {e}")
            traceback.print_exc()
            return Image.new('RGBA', target_size, (255, 255, 255, 255))

    def add_frame(self, image, target_size):
        """添加边框"""
        if not self.frames:
            print("没有可用的边框素材")
            return image
        
        try:
            # 随机选择一个边框
            frame_file = random.choice(self.frames)
            frame_path = os.path.join(self.frame_dir, frame_file)
            
            # 加载边框图像
            frame_image = Image.open(frame_path).convert('RGBA')
            
            # 调整边框大小以匹配目标尺寸
            frame_image = frame_image.resize(target_size, Image.Resampling.LANCZOS)
            
            # 创建一个新图层用于合成
            framed_image = Image.new('RGBA', target_size, (0, 0, 0, 0))
            
            # 先放置基础图像
            framed_image.paste(image, (0, 0))
            
            # 再合成边框图像
            framed_image.alpha_composite(frame_image)
            
            print(f"添加边框: {frame_file}")
            return framed_image
        except Exception as e:
            print(f"添加边框失败: {e}")
            return image

    def create_middle_layer(self, target_size):
        """创建中间层（文本框底图）"""
        try:
            middle_layer = Image.new('RGBA', target_size, (0, 0, 0, 0))
            
            # 1. 首先确定固定的文本区域
            width, height = target_size
            
            # 定义文本区域大小
            header_height = int(height * 0.2)  # 占顶部20%
            header_width = int(width * 0.9)    # 占宽度的90%
            
            # 标题区域的位置（居中）
            title_x = (width - header_width) // 2
            title_y = int(height * 0.16)  # 从原来的0.05(5%)改为0.12(12%)，向下移动
            
            # 保存标题区域信息
            self.title_area = {
                'x': title_x,
                'y': title_y,
                'width': header_width,
                'height': header_height
            }
            
            # 计算额外文本的区域（位于底部区域）
            additional_text_y = int(height * 0.65)  # 位于底部35%的位置
            additional_text_height = int(height * 0.1)  # 占高度的10%
            
            # 保存额外文本区域信息
            self.additional_text_area = {
                'x': int(width * 0.1),  # 左边距10%
                'y': additional_text_y,
                'width': int(width * 0.8),  # 占宽度的80%
                'height': additional_text_height
            }
            
            # 输出文本区域信息
            print("文本区域信息:")
            print(f"主标题区域: x={self.title_area['x']}, y={self.title_area['y']}, "
                  f"宽={self.title_area['width']}, 高={self.title_area['height']}")
            
            # 2. 检查是否使用文本框底图
            use_text_bg = random.random() < self.text_bg_posbility
            print(f"环境变量USE_TEXT_BG设置为: {os.environ.get('USE_TEXT_BG', 'True')}, 是否使用文本框底图: {use_text_bg}")

            if use_text_bg and self.text_bgs:
                print("根据环境变量设置，使用文本框底图")
                # 随机选择文本背景
                text_bg_path = os.path.join(self.text_bg_dir, random.choice(self.text_bgs))
                text_bg = Image.open(text_bg_path).convert('RGBA')
                
                # 计算文本框底图的尺寸，适度放大
                bg_width = int(width * 1.9)  # 宽度为画布宽度的130%
                bg_height = int(height * 0.85)  # 高度为画布高度的50%
                
                # 计算主标题的中心点
                title_center_x = self.title_area['x'] + self.title_area['width'] // 2
                title_center_y = self.title_area['y'] + self.title_area['height'] // 2
                
                # 根据主标题中心点计算底图位置，确保完全对齐
                bg_x = title_center_x - (bg_width // 2)  # 从标题中心点向两侧扩展
                bg_y = title_center_y - (bg_height // 2)  # 从标题中心点向上下扩展
                
                # 调整文本背景大小
                text_bg = text_bg.resize((bg_width, bg_height), Image.Resampling.LANCZOS)
                
                # 创建临时图层并合并
                temp = Image.new('RGBA', target_size, (0, 0, 0, 0))
                temp.paste(text_bg, (bg_x, bg_y), text_bg)
                middle_layer.alpha_composite(temp)
                
                print(f"文本背景: 宽={bg_width}px (画布宽度的{bg_width/width:.1f}倍), "
                      f"高={bg_height}px (画布高度的{bg_height/height:.1f}倍)")
            else:
                print("根据环境变量设置，不使用文本框底图，仅使用固定文本区域")
            
            return middle_layer
        except Exception as e:
            print(f"创建中间层时出错: {str(e)}")
            traceback.print_exc()  # 打印详细错误信息
            return Image.new('RGBA', target_size, (0, 0, 0, 0))

    def create_text_layer(self, target_size, text_data=None):
        """创建文字层"""
        try:
            text_layer = Image.new('RGBA', target_size, (0, 0, 0, 0))
            draw = ImageDraw.Draw(text_layer)
            
            # 使用固定效果：字体蓝色立体效果
            self.selected_effect = "文字蓝色立体效果"
            print(f"使用文字效果: {self.selected_effect}")
            
            # 检查文字数据
            if text_data is None:
                return text_layer
            
            print(f"处理文本数据: {text_data}")

            # 1. 处理主标题
            if hasattr(self, 'title_area') and 'title' in text_data and text_data['title']:
                font_path = self._get_font_path()
                title = text_data['title']
                
                # 使用柠檬黄色作为主标题颜色
                lemon_yellow = (255, 250, 55, 255)  # 柠檬黄色
                
                # 使用统一定义的标题区域
                font, text_width, text_height, x, y = self._calculate_text_layout(
                    draw, font_path, title, self.title_area, size_factor=0.75)
                
                # 绘制主标题文字
                self._draw_text_with_effects(draw, title, font, x, y, 
                                          shadow_offset=8,
                                          color=lemon_yellow)
                
                # 打印调试信息
                self._print_text_debug_info("主标题", font, text_width, x, y, font_path)
                print(f"- 主标题颜色: 柠檬黄色 RGB(255, 250, 55)")
            else:
                print("警告: 无法处理主标题，可能缺少标题数据或title_area未定义")
            
            # 2. 处理副标题（如果有）
            if hasattr(self, 'title_area') and 'subtitle' in text_data and text_data['subtitle']:
                subtitle = text_data['subtitle']
                # 计算副标题区域（在主标题下方）
                subtitle_area = {
                    'x': self.title_area['x'],
                    'y': self.title_area['y'] + self.title_area['height'],
                    'width': self.title_area['width'],
                    'height': int(self.title_area['height'] * 0.5)  # 副标题高度为主标题的一半
                }
                
                # 获取副标题字体和布局
                font, text_width, text_height, x, y = self._calculate_text_layout(
                    draw, font_path, subtitle, subtitle_area, size_factor=0.6)
                
                # 副标题保持白色
                white_color = (255, 255, 255, 255)
                
                # 绘制副标题
                self._draw_text_with_effects(draw, subtitle, font, x, y, 
                                           shadow_offset=8,
                                           color=white_color)
                
                # 打印调试信息
                self._print_text_debug_info("副标题", font, text_width, x, y, font_path)
            
            # 3. 处理额外文本（如果有）
            if 'additional_texts' in text_data and text_data['additional_texts']:
                # 打印接收到的额外文本
                print(f"接收到额外文本数据: {text_data['additional_texts']}")

                # 过滤掉空文本项
                valid_additional_texts = []
                for item in text_data['additional_texts']:
                    if isinstance(item, dict) and 'text' in item and item['text']:
                        valid_additional_texts.append(item)
                    elif isinstance(item, str) and item:
                        # 如果是字符串，转换为字典格式
                        valid_additional_texts.append({"text": item, "position": "middle", "size_factor": 0.5})
                
                print(f"有效额外文本项: {len(valid_additional_texts)}")
                
                if valid_additional_texts and hasattr(self, 'title_area'):
                    # 获取主标题的字体大小
                    main_title_font_size = font.size if 'font' in locals() else 48  # 默认字体大小
                    
                    # 使用固定字体
                    specific_font_path = self.default_font_path
                    # specific_font_path = os.path.join(self.font_dir, "华康海报体简.ttc")
                    if not os.path.isfile(specific_font_path):
                        specific_font_path = font_path if 'font_path' in locals() else self._get_font_path()
                    
                    # 计算额外文本在屏幕上的位置
                    height = target_size[1]
                    width = target_size[0]
                    
                    # 将垂直位置调整到主标题下方
                    title_bottom = self.title_area['y'] + self.title_area['height']
                    extra_text_y_start = title_bottom + int(height * 0.01)  # 从原来的0.05(5%)减小到0.02(2%)
                    extra_text_height = int(height * 0.2)
                    
                    # 安全边距
                    safe_margin_x = int(width * 0.05)
                    max_text_width = width - (safe_margin_x * 2)
                    
                    # 总文本行数
                    total_lines = len(valid_additional_texts)
                    line_height = extra_text_height // total_lines if total_lines > 0 else 0
                    
                    print(f"额外文本区域: y={extra_text_y_start}, 高度={extra_text_height}, 每行高度={line_height}")
                    print(f"文本安全宽度: {max_text_width}px (留出两侧各{safe_margin_x}px安全边距)")
                    print(f"文本颜色: 统一白色")
                    
                    # 渲染每一行文本
                    for i, text_item in enumerate(valid_additional_texts):
                        item_text = text_item['text']
                        
                        # 检查文本内容
                        if not item_text:
                            print(f"警告: 额外文本项 {i+1} 文本为空，跳过")
                            continue
                        
                        # 设置字体大小为主标题的0.8倍或使用指定的size_factor
                        size_factor = text_item.get('size_factor', 0.8)
                        font_size = int(main_title_font_size * size_factor)
                        text_font = ImageFont.truetype(specific_font_path, font_size)
                        
                        # 测量文本宽度并调整
                        text_width = draw.textlength(item_text, font=text_font)
                        
                        # 保护措施：如果文本宽度超出安全区域，逐步缩小字体直到适合
                        while text_width > max_text_width and font_size > int(main_title_font_size * 0.4):
                            size_factor *= 0.95
                            font_size = int(main_title_font_size * size_factor)
                            text_font = ImageFont.truetype(specific_font_path, font_size)
                            text_width = draw.textlength(item_text, font=text_font)
                        
                        # 再次测量调整后的文本尺寸
                        text_bbox = draw.textbbox((0, 0), item_text, font=text_font)
                        text_height = text_bbox[3] - text_bbox[1]
                        
                        # 获取位置参数
                        position = text_item.get('position', 'bottom')
                        
                        # 根据位置设置垂直位置
                        if position == 'top':
                            line_y = int(height * 0.05) + (i * line_height)
                        elif position == 'middle':
                            line_y = int(height * 0.4) + (i * line_height)
                        else:  # position == 'bottom' 或其他
                            # 在底部区域，使用更大的垂直间距，比如整个海报高度的65%到85%
                            bottom_start = int(height * 0.65)
                            bottom_height = int(height * 0.2)
                            bottom_line_height = bottom_height // total_lines if total_lines > 0 else 0
                            line_y = bottom_start + (i * bottom_line_height)
                        
                        # 水平居中位置
                        line_x = (width - text_width) // 2
                        
                        # 统一使用白色文本
                        text_color = (255, 255, 255, 255)  # 白色
                        
                        # 绘制文本
                        self._draw_text_with_effects(draw, item_text, text_font, line_x, line_y, 
                                                   shadow_offset=3,
                                                   color=text_color)
                        
                        # 打印调试信息
                        print(f"额外文本{i+1}: '{item_text}'")
                        print(f"- 文本颜色: 白色")
                        print(f"- 字体大小: {font_size}px (主标题的{size_factor:.2f}倍)")
                        print(f"- 位置: x={line_x}, y={line_y}")
                else:
                    print("无法处理额外文本：没有有效的额外文本项或title_area未定义")

            return text_layer
        except Exception as e:
            print(f"创建文字层时出错: {str(e)}")
            traceback.print_exc()
            return Image.new('RGBA', target_size, (0, 0, 0, 0))

    def _get_font_path(self):
        """获取并验证字体路径"""
        # 获取随机字体
        font_path = self.get_random_font()
        try:
            # 尝试加载字体
            ImageFont.truetype(font_path, size=1)  # 先用小尺寸测试字体是否可用
        except Exception as e:
            print(f"加载字体失败: {str(e)}，使用默认字体")
            font_path = self.default_font_path
        
        return font_path
    
    def _get_text_area(self, text_item, target_size, index):
        """获取文本区域"""
        width, height = target_size
        
        # 根据指定位置创建文本区域
        position = text_item.get('position', 'bottom')
        
        if position == 'custom' and 'x' in text_item and 'y' in text_item:
            # 自定义位置
            text_area = {
                'x': text_item['x'],
                'y': text_item['y'],
                'width': text_item.get('width', width // 2),
                'height': text_item.get('height', height // 10)
            }
        elif position == 'top':
            # 顶部区域
            text_area = {
                'x': int(width * 0.1),
                'y': int(height * 0.05),
                'width': int(width * 0.8),
                'height': int(height * 0.1)
            }
        elif position == 'middle':
            # 中部区域
            text_area = {
                'x': int(width * 0.1),
                'y': int(height * 0.45),
                'width': int(width * 0.8),
                'height': int(height * 0.1)
            }
        else:  # 默认为底部
            # 底部区域，增加随机性
            # 从图像的一半高开始（height * 0.5）到底部的0.9位置之间随机选择
            random_y_position = random.uniform(0.5, 0.85)
            # 水平位置也增加随机性，在10%到30%之间
            random_x_position = random.uniform(0.05, 0.1) 
            
            # 多个底部文本时的偏移
            offset = index * 0.08  
            
            text_area = {
                'x': int(width * random_x_position),
                'y': int(height * (random_y_position + offset)),
                'width': int(width * 0.8),
                'height': int(height * 0.1)
            }
        
        return text_area
    
    def _calculate_text_layout(self, draw, font_path, text, text_area, size_factor=0.85, align_left=False):
        """计算文本布局、字体大小和位置
        
        Args:
            draw: ImageDraw对象
            font_path: 字体路径
            text: 文本内容
            text_area: 文本区域字典
            size_factor: 字体大小因子（相对于区域高度）
            align_left: 是否左对齐
        """
        # 设置初始字体大小
        initial_font_size = int(text_area['height'] * size_factor)
        font = ImageFont.truetype(font_path, initial_font_size)
        
        # 调整字体大小以适应宽度（目标是占据95%的宽度）
        target_width = text_area['width'] * 0.98  # 增加宽度利用率到98%
        text_width = draw.textlength(text, font=font)
        
        # 字体大小调整逻辑优化：先尝试增大字体以更好地填充宽度
        if text_width < target_width * 0.9 and initial_font_size < int(text_area['height'] * 0.98):
            # 如果文本宽度小于目标宽度的90%，尝试增大字体
            while text_width < target_width * 0.9 and initial_font_size < int(text_area['height'] * 0.98):
                initial_font_size += 2
                font = ImageFont.truetype(font_path, initial_font_size)
                text_width = draw.textlength(text, font=font)
        
        # 如果字体太大，再缩小字体以适应宽度
        while text_width > target_width and initial_font_size > 10:
            initial_font_size -= 2
            font = ImageFont.truetype(font_path, initial_font_size)
            text_width = draw.textlength(text, font=font)
        
        # 获取文字高度
        text_bbox = draw.textbbox((0, 0), text, font=font)
        text_height = text_bbox[3] - text_bbox[1]
        
        # 计算位置
        if align_left:
            # 左对齐
            x = text_area['x'] + int(text_area['width'] * 0.05)  # 5% 的左边距
            y = text_area['y'] + (text_area['height'] - text_height) // 2
        else:
            # 居中对齐
            x = text_area['x'] + (text_area['width'] - text_width) // 2
            y = text_area['y'] + (text_area['height'] - text_height) // 2
        
        return font, text_width, text_height, x, y
    
    def _draw_text_with_effects(self, draw, text, font, x, y, shadow_offset=8, color=(255, 255, 255, 255)):
        """绘制带立体效果的文字
        
        Args:
            draw: ImageDraw对象
            text: 文本内容
            font: 字体对象
            x, y: 文本坐标
            shadow_offset: 立体深度
            color: 文本表面颜色
        """
        # 文字颜色使用传入的color参数
        text_color = color
        
        # 蓝色立体效果 - 只用一种深蓝色
        blue_color = (29, 60, 171, 255)  # 深蓝色
        
        # 立体深度 - 使用更大的深度
        depth = 8  # 8像素的立体深度
        
        # 1. 首先绘制深蓝色立体部分
        for i in range(1, depth + 1):
            # 下方
            draw.text((x, y + i), text, font=font, fill=blue_color)
            # 右侧
            draw.text((x + i, y), text, font=font, fill=blue_color)
            # 右下角
            draw.text((x + i, y + i), text, font=font, fill=blue_color)
        
        # 2. 绘制蓝色描边 - 增强文字的边缘清晰度
        stroke_thickness = 2
        
        for dx in range(-stroke_thickness, stroke_thickness+1):
            for dy in range(-stroke_thickness, stroke_thickness+1):
                if dx == 0 and dy == 0:
                    continue
                # 计算当前点到中心的距离
                distance = (dx**2 + dy**2)**0.5
                # 如果距离在描边范围内，绘制蓝色描边
                if distance <= stroke_thickness:
                    draw.text((x + dx, y + dy), text, font=font, fill=blue_color)
        
        # 3. 最后绘制主文字在最上层，使用传入的颜色
        draw.text((x, y), text, font=font, fill=text_color)

    def _print_text_debug_info(self, text_type, font, text_width, x, y, font_path):
        """打印文本调试信息"""
        print(f"- {text_type} 字体大小: {font.size}px")
        print(f"- {text_type} 文本宽度: {text_width}px")
        print(f"- {text_type} 位置: x={x}, y={y}")
        print(f"- {text_type} 使用字体: {os.path.basename(font_path)}")

    def add_stickers(self, poster_image):
        """
        在海报上添加装饰性贴纸
        
        Args:
            poster_image: 要添加贴纸的海报图像对象
            
        Returns:
            添加了贴纸的海报图像对象
        """
        if not hasattr(self, 'sticker_files') or not self.sticker_files:
            print("没有可用的贴纸素材，跳过贴纸添加")
            return poster_image
            
        try:
            # 获取海报尺寸
            width, height = poster_image.size
            
            # 决定是否添加贴纸（50%概率）
            if random.random() < 0.5:
                print("随机决定不添加贴纸")
                return poster_image
                
            # 随机决定添加1-3个贴纸
            sticker_count = random.randint(1, 3)
            print(f"准备添加 {sticker_count} 个贴纸")
            
            # 创建一个新图层用于合成
            result_image = poster_image.copy()
            
            for i in range(sticker_count):
                # 随机选择一个贴纸
                sticker_file = random.choice(self.sticker_files)
                sticker_path = os.path.join(self.sticker_dir, sticker_file)
                
                # 加载贴纸图像
                sticker = Image.open(sticker_path).convert('RGBA')
                
                # 调整贴纸大小（原始尺寸的10%-30%）
                sticker_size_factor = random.uniform(0.1, 0.3)
                new_width = int(width * sticker_size_factor)
                new_height = int(new_width * sticker.height / sticker.width)  # 保持纵横比
                sticker = sticker.resize((new_width, new_height), Image.Resampling.LANCZOS)
                
                # 随机选择贴纸位置（避开中央区域）
                margin = int(width * 0.1)  # 边缘区域的10%
                
                # 生成随机位置（避开中间区域）
                if random.random() < 0.5:  # 左/右边缘
                    x = random.randint(margin, int(width * 0.25)) if random.random() < 0.5 else random.randint(int(width * 0.75), width - new_width - margin)
                    y = random.randint(margin, height - new_height - margin)
                else:  # 上/下边缘
                    x = random.randint(margin, width - new_width - margin)
                    y = random.randint(margin, int(height * 0.25)) if random.random() < 0.5 else random.randint(int(height * 0.75), height - new_height - margin)
                
                # 将贴纸粘贴到结果图像上
                result_image.paste(sticker, (x, y), sticker)
                print(f"添加贴纸 {i+1}: {sticker_file}, 大小: {new_width}x{new_height}, 位置: ({x}, {y})")
            
            return result_image
        except Exception as e:
            print(f"添加贴纸失败: {e}")
            traceback.print_exc()
            return poster_image
        
    def create_poster(self, image_input, text_data):
        """
        Creates a poster by combining the base image, frame (optional), stickers (optional),
        and text layers.

        Args:
            image_input: 底图输入，可以是图片路径字符串或 PIL Image 对象
            text_data: Dictionary containing text information (
                {
                    'title': 'Main Title Text',
                    'subtitle': 'Subtitle Text (optional)',
                    'additional_texts': [{'text': '...', 'position': 'top/bottom/center', 'size_factor': 0.8}, ...]
                }
            ).

        Returns:
            A PIL Image object representing the final poster, or None if creation failed.
        """
        target_size = (900, 1200) # TODO: Make target_size a parameter?
        
        print(f"\n--- Creating Poster --- ")
        if isinstance(image_input, Image.Image):
            print(f"Input: PIL Image 对象，尺寸 {image_input.size}")
        else:
            print(f"Input Image: {image_input}")
        print(f"Text Data: {text_data}")
        
        try:
            # 1. 创建底层（图片）
            base_layer = self.create_base_layer(image_input, target_size)
            if not base_layer:
                raise ValueError("Failed to create base layer.")
            print("Base layer created.")

            # 2. (可选) 添加边框 - 根据计数器决定
            # if self.poster_count % 5 == 0:  # 每5张海报添加一次边框
            if random.random() < self.img_frame_posbility:
                print("Attempting to add frame...")
                base_layer = self.add_frame(base_layer, target_size)
            else:
                print("Skipping frame addition.")
            self.poster_count += 1 # 增加计数器
            
            # 3. 创建中间层（文本框底图）
            # middle_layer 包含文本区域定义 (self.title_area, self.additional_text_area)
            middle_layer = self.create_middle_layer(target_size)
            print("Middle layer (text areas defined) created.")
            
            # 4. 创建文本层
            text_layer = self.create_text_layer(target_size, text_data)
            print("Text layer created.")
            
            # 5. 合成图层
            # Start with the base layer (which might already have a frame)
            final_poster = base_layer
            
            # Add middle layer (text backgrounds)
            final_poster.alpha_composite(middle_layer)
            
            # Add text layer
            final_poster.alpha_composite(text_layer)
            
            # (可选) 添加贴纸
            final_poster = self.add_stickers(final_poster)
            print("Layers composed.")
            
            # 转换回 RGB 以保存为 JPG/PNG (移除 alpha通道)
            final_poster_rgb = final_poster.convert("RGB")
            
            # 移除保存逻辑，直接返回 Image 对象
            # final_save_path = os.path.join(self.output_dir, output_name)
            # os.makedirs(os.path.dirname(final_save_path), exist_ok=True)
            # final_poster_rgb.save(final_save_path)
            # print(f"Final poster saved to: {final_save_path}")
            # return final_save_path
            return final_poster_rgb
            
        except Exception as e:
            print(f"Error creating poster: {e}")
            traceback.print_exc()
            return None

    def set_img_frame_possibility(self, img_frame_possibility):
        self.img_frame_posbility = img_frame_possibility

    def set_text_bg_possibility(self, text_bg_possibility):
        self.text_bg_posbility = text_bg_possibility

def main():    
    # 设置是否使用文本框底图（True为使用，False为不使用）
    os.environ['USE_TEXT_BG'] = 'False'  # 或 'True'
    print(f"设置环境变量USE_TEXT_BG为: {os.environ['USE_TEXT_BG']}")
    
    # 创建生成器实例
    generator = PosterGenerator("/root/autodl-tmp/poster_baseboard_0403")
    
    poster_config_path = "/root/autodl-tmp/poster_generate_result/2025-04-16_20-49-32.json"
    poster_config = PosterConfig(poster_config_path)
    for item in poster_config.get_config():
        text_data = {
                    "title": f"{item['main_title']}",
                    "subtitle": "",
                    "additional_texts": [
                    {"text": f"{item['texts'][0]}", "position": "bottom", "size_factor": 0.5},
                    {"text": f"{item['texts'][1]}", "position": "bottom", "size_factor": 0.5}
                            ]
                        }
        # 处理目录中的所有图片
        img_path = "/root/autodl-tmp/poster_baseboard_0403/output_collage/random_collage_1_collage.png"
        
        # 先加载图片，然后传递 PIL Image 对象
        try:
            # 先加载图片
            collage_img = Image.open(img_path).convert('RGBA')
            print(f"已加载拼贴图: {img_path}, 尺寸: {collage_img.size}")
            
            # 传递图片对象而不是路径
            generator.create_poster(collage_img, text_data)
        except Exception as e:
            print(f"加载或处理图片时出错: {e}")
            traceback.print_exc()
            # 失败时回退到使用路径
            generator.create_poster(img_path, text_data)

if __name__ == "__main__":
    main()
