"""
功能 1: 颜色智能扩展
使用 LAB 色彩空间插值生成更多颜色
"""
import warnings
from typing import List, Tuple


def hex_to_rgb(hex_color: str) -> Tuple[int, int, int]:
    """十六进制转 RGB"""
    hex_color = hex_color.lstrip('#')
    return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))


def rgb_to_hex(rgb: Tuple[int, int, int]) -> str:
    """RGB 转十六进制"""
    return '#{:02x}{:02x}{:02x}'.format(
        max(0, min(255, int(rgb[0]))),
        max(0, min(255, int(rgb[1]))),
        max(0, min(255, int(rgb[2])))
    )


def rgb_to_lab(rgb: Tuple[int, int, int]) -> Tuple[float, float, float]:
    """
    RGB 转 LAB 色彩空间
    使用简化的转换公式，实际生产中可以使用 colorspacious 库
    """
    # 归一化 RGB
    r, g, b = rgb[0] / 255.0, rgb[1] / 255.0, rgb[2] / 255.0
    
    # Gamma 校正
    def gamma_correction(val):
        if val > 0.04045:
            return ((val + 0.055) / 1.055) ** 2.4
        return val / 12.92
    
    r = gamma_correction(r)
    g = gamma_correction(g)
    b = gamma_correction(b)
    
    # RGB -> XYZ (D65 illuminant)
    x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375
    y = r * 0.2126729 + g * 0.7151522 + b * 0.0721750
    z = r * 0.0193339 + g * 0.1191920 + b * 0.9503041
    
    # XYZ -> LAB
    def f(t):
        delta = 6 / 29
        if t > delta ** 3:
            return t ** (1/3)
        return t / (3 * delta ** 2) + 4 / 29
    
    # D65 白点
    xn, yn, zn = 0.95047, 1.00000, 1.08883
    
    l = 116 * f(y / yn) - 16
    a = 500 * (f(x / xn) - f(y / yn))
    b_val = 200 * (f(y / yn) - f(z / zn))
    
    return (l, a, b_val)


def lab_to_rgb(lab: Tuple[float, float, float]) -> Tuple[int, int, int]:
    """LAB 转 RGB 色彩空间"""
    l, a, b = lab
    
    # LAB -> XYZ
    def f_inv(t):
        delta = 6 / 29
        if t > delta:
            return t ** 3
        return 3 * delta ** 2 * (t - 4 / 29)
    
    # D65 白点
    xn, yn, zn = 0.95047, 1.00000, 1.08883
    
    fy = (l + 16) / 116
    fx = fy + a / 500
    fz = fy - b / 200
    
    x = xn * f_inv(fx)
    y = yn * f_inv(fy)
    z = zn * f_inv(fz)
    
    # XYZ -> RGB
    r = x * 3.2404542 + y * -1.5371385 + z * -0.4985314
    g = x * -0.9692660 + y * 1.8760108 + z * 0.0415560
    b_val = x * 0.0556434 + y * -0.2040259 + z * 1.0572252
    
    # 反 Gamma 校正
    def inv_gamma_correction(val):
        if val > 0.0031308:
            return 1.055 * (val ** (1/2.4)) - 0.055
        return 12.92 * val
    
    r = inv_gamma_correction(r)
    g = inv_gamma_correction(g)
    b_val = inv_gamma_correction(b_val)
    
    # 转换到 0-255 并钳制
    r = max(0, min(255, int(r * 255 + 0.5)))
    g = max(0, min(255, int(g * 255 + 0.5)))
    b_val = max(0, min(255, int(b_val * 255 + 0.5)))
    
    return (r, g, b_val)


def intelligent_color_expansion(base_colors: List[str], n_needed: int) -> List[str]:
    """
    智能扩展颜色：在 LAB 色彩空间插值
    
    Args:
        base_colors: 基础调色板（hex 格式）
        n_needed: 需要的颜色数量
    
    Returns:
        扩展后的颜色列表
        
    Example:
        >>> base = ['#E64B35', '#4DBBD5', '#00A087']
        >>> expanded = intelligent_color_expansion(base, 10)
        >>> len(expanded)
        10
    """
    if n_needed <= len(base_colors):
        return base_colors[:n_needed]
    
    if n_needed > len(base_colors):
        warnings.warn(
            f"Expanding color palette from {len(base_colors)} to {n_needed} colors "
            f"using LAB space interpolation. For better distinction with many categories, "
            f"consider using different visual encodings (markers, line styles, etc.)",
            UserWarning
        )
    
    try:
        # 转换为 RGB
        rgb_colors = [hex_to_rgb(c) for c in base_colors]
        
        # 转换为 LAB
        lab_colors = [rgb_to_lab(rgb) for rgb in rgb_colors]
        
        # 在 LAB 空间插值
        expanded = []
        step = (len(lab_colors) - 1) / (n_needed - 1) if n_needed > 1 else 0
        
        for i in range(n_needed):
            idx = i * step
            base_idx = int(idx)
            weight = idx - base_idx
            
            if base_idx >= len(lab_colors) - 1:
                # 最后一个颜色
                lab = lab_colors[-1]
            else:
                # 线性插值
                l1, a1, b1 = lab_colors[base_idx]
                l2, a2, b2 = lab_colors[base_idx + 1]
                
                lab = (
                    l1 + (l2 - l1) * weight,
                    a1 + (a2 - a1) * weight,
                    b1 + (b2 - b1) * weight
                )
            
            # 转回 RGB 和 Hex
            rgb = lab_to_rgb(lab)
            hex_color = rgb_to_hex(rgb)
            expanded.append(hex_color)
        
        return expanded
    
    except Exception as e:
        warnings.warn(
            f"Failed to expand colors using LAB interpolation: {e}. "
            f"Falling back to simple cycling.",
            UserWarning
        )
        # 降级方案：简单循环
        return [base_colors[i % len(base_colors)] for i in range(n_needed)]


if __name__ == "__main__":
    # 测试
    base = ['#E64B35', '#4DBBD5', '#00A087', '#3C5488', '#F39B7F']
    print(f"Base colors: {base}")
    expanded = intelligent_color_expansion(base, 15)
    print(f"Expanded to 15 colors: {expanded}")





