#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Collage Template
拼贴风格海报模板 - 重构版本，支持多图像拼贴效果
"""

import logging
import random
from typing import Dict, Any, Optional, Tuple, List
from PIL import Image, ImageDraw

from .base_template import BaseTemplate
from ....exceptions import PosterGenerationError

logger = logging.getLogger(__name__)


class CollageTemplate(BaseTemplate):
    """
    拼贴风格模板 - 重构版本
    适用于多图展示、产品集合、旅游相册等场景
    特点是动态网格布局，支持多种拼贴样式
    """
    
    SUPPORTED_FEATURES = [
        "multi_image_layout",
        "dynamic_grid",
        "flexible_positioning", 
        "overlay_text",
        "border_effects"
    ]

    def __init__(self, size: Tuple[int, int] = (900, 1200), config: Optional[Dict[str, Any]] = None):
        super().__init__(size, config)
        
        # 拼贴模板特定配置
        self.grid_config = {
            "max_images": 6,
            "min_image_size": 150,
            "grid_padding": 10,
            "border_width": 3,
            "border_color": (255, 255, 255),
            "text_overlay_height": 200
        }
        
        logger.debug("CollageTemplate 初始化完成")

    def generate(
        self,
        images: List[Image.Image],
        content: Optional[Dict[str, Any]] = None,
        layout_style: str = "dynamic",
        max_images: Optional[int] = None,
        **kwargs
    ) -> Image.Image:
        """
        生成Collage风格海报

        Args:
            images: 图像列表
            content: 文本内容字典
            layout_style: 布局风格 (dynamic, grid, mosaic)
            max_images: 最大图像数量
            **kwargs: 其他参数

        Returns:
            生成的海报图像

        Raises:
            PosterGenerationError: 生成失败时抛出
        """
        try:
            # 验证输入
            if not self._validate_inputs(['images'], images=images):
                raise PosterGenerationError("输入验证失败")
            
            if not self._validate_images(images):
                raise PosterGenerationError("图像验证失败")
            
            if content and not self._validate_content(content):
                raise PosterGenerationError("内容验证失败")
            
            # 使用默认内容（如果未提供）
            if content is None:
                content = self._get_default_content()

            # 限制图像数量
            max_imgs = max_images or self.grid_config["max_images"]
            display_images = images[:max_imgs]
            
            # 创建背景
            canvas = self._create_collage_background()
            
            # 根据布局风格安排图像
            if layout_style == "grid":
                canvas = self._create_grid_layout(canvas, display_images)
            elif layout_style == "mosaic":
                canvas = self._create_mosaic_layout(canvas, display_images)
            else:  # dynamic
                canvas = self._create_dynamic_layout(canvas, display_images)
            
            # 添加文本覆盖层
            canvas = self._add_text_overlay(canvas, content)
            
            return canvas

        except Exception as e:
            error_msg = f"CollageTemplate生成失败: {str(e)}"
            logger.error(error_msg, exc_info=True)
            raise PosterGenerationError(error_msg)

    def _get_default_content(self) -> Dict[str, Any]:
        """获取默认内容"""
        return {
            "title": "精彩瞬间",
            "content": "记录生活中的美好时光，每一张图片都是珍贵的回忆。",
            "tags": ["回忆", "美好", "瞬间"],
            "call_to_action": "查看更多"
        }

    def _create_collage_background(self) -> Image.Image:
        """创建拼贴背景"""
        # 创建渐变背景
        colors = self.get_color_theme()
        if colors:
            bg_color1, bg_color2 = colors[0], colors[1] if len(colors) > 1 else colors[0]
            # 使用较浅的颜色作为背景
            bg_color1 = tuple(min(255, c + 50) for c in bg_color1)
            bg_color2 = tuple(min(255, c + 50) for c in bg_color2)
        else:
            bg_color1, bg_color2 = (240, 240, 240), (220, 220, 220)
        
        return self.create_gradient_background(bg_color1, bg_color2)

    def _create_grid_layout(self, canvas: Image.Image, images: List[Image.Image]) -> Image.Image:
        """创建网格布局"""
        result = canvas.copy()
        
        if not images:
            return result
        
        # 计算网格尺寸
        num_images = len(images)
        if num_images <= 2:
            cols, rows = num_images, 1
        elif num_images <= 4:
            cols, rows = 2, 2
        elif num_images <= 6:
            cols, rows = 3, 2
        else:
            cols, rows = 3, 3
        
        # 预留文本区域
        text_height = self.grid_config["text_overlay_height"]
        available_height = self.height - text_height
        
        # 计算单元格尺寸
        padding = self.grid_config["grid_padding"]
        cell_width = (self.width - padding * (cols + 1)) // cols
        cell_height = (available_height - padding * (rows + 1)) // rows
        
        # 放置图像
        for i, img in enumerate(images[:cols * rows]):
            row = i // cols
            col = i % cols
            
            # 计算位置
            x = padding + col * (cell_width + padding)
            y = padding + row * (cell_height + padding)
            
            # 调整图像尺寸
            resized_img = self.image_processor.resize_image(
                img, (cell_width, cell_height), keep_aspect=True, crop=True
            )
            
            # 添加边框
            bordered_img = self._add_image_border(resized_img)
            
            # 粘贴到画布
            result.paste(bordered_img, (x, y))
        
        return result

    def _create_dynamic_layout(self, canvas: Image.Image, images: List[Image.Image]) -> Image.Image:
        """创建动态布局"""
        result = canvas.copy()
        
        if not images:
            return result
        
        # 预留文本区域
        text_height = self.grid_config["text_overlay_height"]
        available_height = self.height - text_height
        
        # 动态计算图像位置和尺寸
        positions = self._calculate_dynamic_positions(len(images), available_height)
        
        for i, (img, pos) in enumerate(zip(images, positions)):
            x, y, width, height = pos
            
            # 调整图像尺寸
            resized_img = self.image_processor.resize_image(
                img, (width, height), keep_aspect=True, crop=True
            )
            
            # 添加边框和阴影效果
            bordered_img = self._add_image_border(resized_img)
            shadow_img = self.image_processor.create_shadow(
                bordered_img, offset=(5, 5), blur_radius=8
            )
            
            # 粘贴到画布
            result.paste(shadow_img, (x, y), shadow_img if shadow_img.mode == "RGBA" else None)
        
        return result

    def _create_mosaic_layout(self, canvas: Image.Image, images: List[Image.Image]) -> Image.Image:
        """创建马赛克布局"""
        result = canvas.copy()
        
        if not images:
            return result
        
        # 简化的马赛克布局：不规则网格
        text_height = self.grid_config["text_overlay_height"]
        available_height = self.height - text_height
        
        # 创建不规则的位置列表
        positions = []
        if len(images) >= 1:
            # 大图在左上
            positions.append((20, 20, self.width // 2 - 30, available_height // 2 - 30))
        
        if len(images) >= 2:
            # 中等图在右上
            positions.append((self.width // 2 + 10, 20, self.width // 2 - 30, available_height // 3 - 20))
        
        if len(images) >= 3:
            # 小图在右中
            positions.append((self.width // 2 + 10, available_height // 3 + 10, self.width // 2 - 30, available_height // 4))
        
        if len(images) >= 4:
            # 横图在底部
            positions.append((20, available_height // 2 + 10, self.width - 40, available_height // 3))
        
        # 添加更多位置...
        remaining_images = len(images) - len(positions)
        if remaining_images > 0:
            # 为剩余图像创建小位置
            small_size = 120
            start_x = 20
            start_y = available_height - small_size - 20
            for i in range(remaining_images):
                x = start_x + i * (small_size + 10)
                if x + small_size < self.width:
                    positions.append((x, start_y, small_size, small_size))
        
        # 放置图像
        for i, (img, pos) in enumerate(zip(images, positions)):
            x, y, width, height = pos
            
            # 调整图像尺寸
            resized_img = self.image_processor.resize_image(
                img, (width, height), keep_aspect=True, crop=True
            )
            
            # 添加随机旋转效果
            angle = random.uniform(-5, 5)
            rotated_img = resized_img.rotate(angle, expand=True, fillcolor=(255, 255, 255))
            
            # 添加边框
            bordered_img = self._add_image_border(rotated_img)
            
            # 粘贴到画布
            result.paste(bordered_img, (x, y), bordered_img if bordered_img.mode == "RGBA" else None)
        
        return result

    def _calculate_dynamic_positions(self, num_images: int, available_height: int) -> List[Tuple[int, int, int, int]]:
        """计算动态位置"""
        positions = []
        
        if num_images == 1:
            # 单张图片，居中大尺寸
            width, height = self.width - 100, available_height - 100
            x, y = 50, 50
            positions.append((x, y, width, height))
            
        elif num_images == 2:
            # 两张图片，左右分布
            width = (self.width - 60) // 2
            height = available_height - 100
            positions.append((20, 50, width, height))
            positions.append((40 + width, 50, width, height))
            
        else:
            # 多张图片，混合布局
            padding = 15
            base_size = min(200, (self.width - padding * 4) // 3)
            
            for i in range(num_images):
                if i < 3:
                    # 顶行三张
                    x = padding + i * (base_size + padding)
                    y = padding
                    width = height = base_size
                elif i < 5:
                    # 底行两张大一些
                    width = base_size * 1.3
                    height = base_size * 1.1
                    x = padding + (i - 3) * (width + padding * 2)
                    y = padding * 2 + base_size + padding
                else:
                    # 额外的图片小尺寸
                    width = height = base_size * 0.7
                    x = self.width - width - padding
                    y = padding + (i - 5) * (height + padding)
                
                positions.append((int(x), int(y), int(width), int(height)))
        
        return positions

    def _add_image_border(self, image: Image.Image) -> Image.Image:
        """为图像添加边框"""
        border_width = self.grid_config["border_width"]
        border_color = self.grid_config["border_color"]
        
        # 创建带边框的图像
        bordered_size = (image.width + border_width * 2, image.height + border_width * 2)
        bordered_img = Image.new("RGB", bordered_size, border_color)
        bordered_img.paste(image, (border_width, border_width))
        
        return bordered_img

    def _add_text_overlay(self, canvas: Image.Image, content: Dict[str, Any]) -> Image.Image:
        """添加文本覆盖层"""
        result = canvas.copy()
        
        # 文本区域在底部
        text_height = self.grid_config["text_overlay_height"]
        text_y_start = self.height - text_height
        
        # 创建半透明文本背景
        overlay = Image.new("RGBA", (self.width, text_height), (0, 0, 0, 180))
        result.paste(overlay, (0, text_y_start), overlay)
        
        # 渲染文本内容
        current_y = text_y_start + 20
        
        # 标题
        title = content.get("title", "")
        if title:
            title_x = 30
            result = self.text_renderer.render_text(
                image=result,
                text=title,
                position=(title_x, current_y),
                font_size=32,
                color=(255, 255, 255)
            )
            current_y += 32 + 15
        
        # 内容
        main_content = content.get("content", "")
        if main_content:
            content_x = 30
            wrapped_lines = self.text_renderer.wrap_text(
                text=main_content,
                max_width=self.width - 60,
                font_size=18
            )
            
            result = self.text_renderer.render_multiline_text(
                image=result,
                text_lines=wrapped_lines[:3],  # 最多3行
                start_position=(content_x, current_y),
                font_size=18,
                line_spacing=5,
                color=(220, 220, 220),
                align="left"
            )
            current_y += len(wrapped_lines[:3]) * (18 + 5) + 15
        
        # 标签和CTA在同一行
        tags = content.get("tags", [])
        cta = content.get("call_to_action", "")
        
        if tags:
            tags_text = " ".join([f"#{tag}" for tag in tags])
            result = self.text_renderer.render_text(
                image=result,
                text=tags_text,
                position=(30, current_y),
                font_size=14,
                color=(180, 180, 180)
            )
        
        if cta:
            cta_x = self.width - 120
            # 简单的CTA按钮
            draw = ImageDraw.Draw(result)
            draw.rounded_rectangle(
                [cta_x, current_y - 5, cta_x + 100, current_y + 25],
                radius=15,
                fill=(255, 100, 100),
                outline=(255, 255, 255),
                width=1
            )
            
            result = self.text_renderer.render_text(
                image=result,
                text=cta,
                position=(cta_x + 50, current_y + 2),
                font_size=14,
                color=(255, 255, 255),
                anchor="mm"
            )
        
        return result 