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

"""
Base Template
海报模板的抽象基类 - 重构版本，使用配置化系统
"""

import logging
from abc import ABC, abstractmethod
from typing import Tuple, Dict, Any, Optional, List
from PIL import Image, ImageDraw
from pathlib import Path

from ...exceptions import PosterGenerationError, ResourceNotFoundError
from ..utils import ImageProcessor, TextRenderer

logger = logging.getLogger(__name__)


class BaseTemplate(ABC):
    """
    所有海报模板的抽象基类 - 重构版本
    定义了模板的通用接口和基础功能，支持配置化
    """
    
    SUPPORTED_FEATURES = []  # 子类应该定义支持的功能列表
    
    def __init__(self, size: Tuple[int, int] = (900, 1200), config: Optional[Dict[str, Any]] = None):
        """
        初始化基础模板

        Args:
            size: 海报尺寸 (宽, 高)
            config: 模板配置字典
        """
        self.width, self.height = size
        self.size = size
        self.config = config or {}
        
        # 初始化工具类
        self.image_processor = ImageProcessor()
        
        # 初始化文本渲染器
        font_directory = self.config.get("font_directory")
        self.text_renderer = TextRenderer(
            font_dir=font_directory,
            font_configs=self.config.get("font_configs", {})
        )
        
        self.logger = logging.getLogger(self.__class__.__name__)
        
        # 验证配置
        self._validate_config()
        
        logger.debug(f"模板 {self.__class__.__name__} 初始化完成，尺寸: {size}")

    def _validate_config(self) -> None:
        """验证模板配置"""
        try:
            # 检查字体目录
            font_dir = self.config.get("font_directory")
            if font_dir and not Path(font_dir).exists():
                logger.warning(f"字体目录不存在: {font_dir}")
            
            # 检查颜色主题
            color_themes = self.config.get("color_themes", {})
            if not color_themes:
                logger.warning("未配置颜色主题，将使用默认颜色")
            
        except Exception as e:
            logger.warning(f"配置验证失败: {e}")

    @abstractmethod
    def generate(self, **kwargs) -> Image.Image:
        """
        生成海报的核心方法
        每个子类必须实现此方法

        Args:
            **kwargs: 包含生成海报所需的所有动态参数，如图片、文案内容等

        Returns:
            生成的海报图像

        Raises:
            PosterGenerationError: 生成失败时抛出
        """
        pass

    def get_config(self) -> Dict[str, Any]:
        """获取模板配置"""
        return {
            "class_name": self.__class__.__name__,
            "size": self.size,
            "supported_features": self.SUPPORTED_FEATURES,
            "config": self.config
        }

    def create_canvas(self, background_color: Optional[Tuple[int, int, int, int]] = None) -> Image.Image:
        """创建一个指定尺寸和颜色的空白画布"""
        color = background_color or (255, 255, 255, 255)
        return Image.new("RGBA", self.size, color)

    def create_gradient_background(
        self, 
        top_color: Tuple[int, int, int],
        bottom_color: Tuple[int, int, int],
        direction: str = "vertical"
    ) -> Image.Image:
        """
        创建渐变背景图

        Args:
            top_color: 顶部颜色 (R, G, B)
            bottom_color: 底部颜色 (R, G, B)
            direction: 渐变方向 ("vertical" 或 "horizontal")

        Returns:
            渐变背景图像
        """
        canvas = Image.new("RGBA", self.size)
        draw = ImageDraw.Draw(canvas)
        
        r1, g1, b1 = top_color
        r2, g2, b2 = bottom_color
        
        if direction == "vertical":
            for i in range(self.height):
                ratio = i / self.height
                r = int(r1 * (1 - ratio) + r2 * ratio)
                g = int(g1 * (1 - ratio) + g2 * ratio)
                b = int(b1 * (1 - ratio) + b2 * ratio)
                draw.line([(0, i), (self.width, i)], fill=(r, g, b, 255))
        else:  # horizontal
            for i in range(self.width):
                ratio = i / self.width
                r = int(r1 * (1 - ratio) + r2 * ratio)
                g = int(g1 * (1 - ratio) + g2 * ratio)
                b = int(b1 * (1 - ratio) + b2 * ratio)
                draw.line([(i, 0), (i, self.height)], fill=(r, g, b, 255))
                
        return canvas

    def get_color_theme(self, theme_name: Optional[str] = None) -> Tuple[Tuple[int, int, int], ...]:
        """
        获取颜色主题

        Args:
            theme_name: 主题名称，如果为None则使用默认主题

        Returns:
            颜色元组
        """
        color_themes = self.config.get("color_themes", {})
        
        if not color_themes:
            # 使用默认颜色
            return ((0, 30, 80), (20, 120, 220))
        
        if theme_name and theme_name in color_themes:
            theme_colors = color_themes[theme_name]
        else:
            # 使用默认主题或第一个可用主题
            default_theme = self.config.get("default_theme")
            if default_theme and default_theme in color_themes:
                theme_colors = color_themes[default_theme]
            else:
                theme_colors = next(iter(color_themes.values()))
        
        # 确保返回正确的格式
        if isinstance(theme_colors, list) and len(theme_colors) >= 2:
            return tuple(tuple(color) for color in theme_colors)
        else:
            logger.warning(f"颜色主题格式错误: {theme_colors}")
            return ((0, 30, 80), (20, 120, 220))

    def apply_text_effects(
        self, 
        image: Image.Image, 
        text: str, 
        position: Tuple[int, int],
        font_size: int = 24,
        text_color: Tuple[int, int, int] = (255, 255, 255),
        effects: Optional[Dict[str, Any]] = None
    ) -> Image.Image:
        """
        应用文本效果

        Args:
            image: 目标图像
            text: 文本内容
            position: 文本位置
            font_size: 字体大小
            text_color: 文本颜色
            effects: 效果配置

        Returns:
            应用效果后的图像
        """
        if not effects:
            effects = self.config.get("text_effects", {})
        
        return self.text_renderer.render_text_with_effects(
            image=image,
            text=text,
            position=position,
            font_size=font_size,
            color=text_color,
            effects=effects
        )

    def _validate_inputs(self, required_keys: List[str], **kwargs) -> bool:
        """
        验证输入参数

        Args:
            required_keys: 必需的参数键列表
            **kwargs: 输入参数

        Returns:
            验证是否通过
        """
        for key in required_keys:
            if key not in kwargs or kwargs[key] is None:
                self.logger.error(f"生成海报失败: 缺少必需的参数 '{key}'")
                return False
        return True

    def _validate_images(self, images: List[Image.Image]) -> bool:
        """
        验证图像列表

        Args:
            images: 图像列表

        Returns:
            验证是否通过
        """
        if not images:
            self.logger.error("生成海报失败: 未提供图像")
            return False
        
        for i, img in enumerate(images):
            if not isinstance(img, Image.Image):
                self.logger.error(f"图像 {i} 不是有效的PIL图像对象")
                return False
        
        return True

    def _validate_content(self, content: Dict[str, Any]) -> bool:
        """
        验证内容格式

        Args:
            content: 内容字典

        Returns:
            验证是否通过
        """
        required_fields = ["title", "content"]
        
        for field in required_fields:
            if field not in content or not content[field]:
                self.logger.error(f"内容缺少必需字段: {field}")
                return False
        
        return True

    def resize_to_target(self, image: Image.Image, target_size: Optional[Tuple[int, int]] = None) -> Image.Image:
        """
        调整图像到目标尺寸

        Args:
            image: 源图像
            target_size: 目标尺寸，如果为None则使用模板尺寸

        Returns:
            调整后的图像
        """
        if target_size is None:
            target_size = self.size
        
        return self.image_processor.resize_image(image, target_size, keep_aspect=True)

    def get_available_themes(self) -> List[str]:
        """获取可用的颜色主题列表"""
        return list(self.config.get("color_themes", {}).keys())

    def get_template_info(self) -> Dict[str, Any]:
        """获取模板信息"""
        return {
            "name": self.__class__.__name__,
            "size": self.size,
            "supported_features": self.SUPPORTED_FEATURES,
            "available_themes": self.get_available_themes(),
            "config_keys": list(self.config.keys())
        } 