"""
功能 4: 图表类型自动适配
根据图表类型自动调整配色策略
"""
import warnings
from typing import List, Dict, Optional, Tuple


def detect_chart_type(ax) -> Dict[str, any]:
    """
    检测图表类型和特征
    
    Args:
        ax: matplotlib axes 对象
    
    Returns:
        字典包含：
        - type: 图表类型 ('line', 'scatter', 'bar', 'mixed', 'unknown')
        - n_lines: 线条数量
        - n_scatter: 散点集合数量
        - n_bars: 柱状图数量
        - complexity: 复杂度 ('simple', 'medium', 'complex')
    """
    try:
        from matplotlib.lines import Line2D
        from matplotlib.patches import Rectangle
        from matplotlib.collections import PathCollection
    except ImportError:
        return {"type": "unknown", "complexity": "simple"}
    
    # 统计各类图表元素
    n_lines = len([obj for obj in ax.get_children() if isinstance(obj, Line2D)])
    n_scatter = len([obj for obj in ax.get_children() if isinstance(obj, PathCollection)])
    n_bars = len([obj for obj in ax.patches if isinstance(obj, Rectangle)])
    
    # 判断主要类型
    chart_type = "unknown"
    if n_lines > n_scatter and n_lines > n_bars:
        chart_type = "line"
    elif n_scatter > n_lines and n_scatter > n_bars:
        chart_type = "scatter"
    elif n_bars > n_lines and n_bars > n_scatter:
        chart_type = "bar"
    elif n_lines > 0 or n_scatter > 0 or n_bars > 0:
        chart_type = "mixed"
    
    # 判断复杂度
    total_elements = n_lines + n_scatter + n_bars
    if total_elements <= 3:
        complexity = "simple"
    elif total_elements <= 7:
        complexity = "medium"
    else:
        complexity = "complex"
    
    return {
        "type": chart_type,
        "n_lines": n_lines,
        "n_scatter": n_scatter,
        "n_bars": n_bars,
        "total_elements": total_elements,
        "complexity": complexity
    }


def adapt_colors_for_chart(colors: List[str], 
                           chart_info: Dict,
                           strategy: str = "auto") -> Tuple[List[str], Dict]:
    """
    根据图表类型调整颜色策略
    
    Args:
        colors: 基础颜色列表
        chart_info: 图表信息（来自 detect_chart_type）
        strategy: 适配策略
            - "auto": 自动选择最佳策略
            - "high_contrast": 高对比度（适合复杂图表）
            - "harmonious": 和谐配色（适合简单图表）
            - "none": 不适配
    
    Returns:
        (adapted_colors, recommendations)
        - adapted_colors: 适配后的颜色列表
        - recommendations: 推荐的视觉编码建议
    """
    if strategy == "none":
        return colors, {}
    
    recommendations = {
        "add_markers": False,
        "add_linestyles": False,
        "add_hatches": False,
        "increase_linewidth": False,
        "add_labels": False,
        "reason": ""
    }
    
    chart_type = chart_info.get("type", "unknown")
    complexity = chart_info.get("complexity", "simple")
    total_elements = chart_info.get("total_elements", 0)
    
    # 策略 1: 复杂线条图 - 建议添加 markers
    if chart_type == "line" and complexity == "complex":
        recommendations["add_markers"] = True
        recommendations["reason"] = (
            f"Detected {total_elements} lines. Consider using markers "
            f"to improve distinguishability."
        )
        warnings.warn(
            f"Chart has {total_elements} lines which may be hard to distinguish. "
            f"Huez recommends adding markers: plt.plot(..., marker='o')",
            UserWarning
        )
    
    # 策略 2: 中等复杂度 - 建议线型变化
    elif chart_type == "line" and complexity == "medium":
        if total_elements > 5:
            recommendations["add_linestyles"] = True
            recommendations["reason"] = (
                f"Detected {total_elements} lines. Consider using different "
                f"line styles for better distinction."
            )
    
    # 策略 3: 复杂柱状图 - 建议添加图案
    elif chart_type == "bar" and complexity == "complex":
        recommendations["add_hatches"] = True
        recommendations["reason"] = (
            f"Detected {total_elements} bars. Consider using hatches "
            f"to improve distinguishability in grayscale."
        )
    
    # 策略 4: 复杂散点图 - 建议增大点的尺寸
    elif chart_type == "scatter" and complexity == "complex":
        recommendations["increase_linewidth"] = True
        recommendations["reason"] = (
            f"Detected {total_elements} scatter groups. Consider using "
            f"different marker sizes or styles."
        )
    
    # 策略 5: 高复杂度 - 建议简化或分组
    if total_elements > 10:
        recommendations["add_labels"] = True
        recommendations["reason"] += (
            f" Chart complexity is high ({total_elements} elements). "
            f"Consider grouping categories or using interactive visualization."
        )
        warnings.warn(
            f"Chart has {total_elements} elements which may be overwhelming. "
            f"Consider grouping categories or using faceted plots.",
            UserWarning
        )
    
    # 颜色适配：对于复杂图表，增加对比度
    adapted_colors = colors.copy()
    
    if complexity == "complex" and strategy == "auto":
        # 对于复杂图表，尝试增加颜色间的对比度
        # 这里返回原始颜色，实际可以进行进一步的颜色调整
        pass
    
    return adapted_colors, recommendations


def generate_markers(n: int) -> List[str]:
    """
    生成 n 个不同的 marker 样式
    
    Args:
        n: 需要的 marker 数量
    
    Returns:
        marker 样式列表
    """
    base_markers = ['o', 's', '^', 'v', 'D', 'p', '*', 'h', 'X', 'P', '<', '>', 'd']
    if n <= len(base_markers):
        return base_markers[:n]
    # 如果需要更多，重复使用
    return [base_markers[i % len(base_markers)] for i in range(n)]


def generate_linestyles(n: int) -> List[str]:
    """
    生成 n 个不同的线型样式
    
    Args:
        n: 需要的线型数量
    
    Returns:
        线型样式列表
    """
    base_styles = ['-', '--', '-.', ':']
    if n <= len(base_styles):
        return base_styles[:n]
    # 如果需要更多，重复使用
    return [base_styles[i % len(base_styles)] for i in range(n)]


def generate_hatches(n: int) -> List[str]:
    """
    生成 n 个不同的填充图案
    
    Args:
        n: 需要的图案数量
    
    Returns:
        图案样式列表
    """
    base_hatches = ['', '///', '\\\\\\', '|||', '---', '+++', 'xxx', 'ooo', 'OOO', '...']
    if n <= len(base_hatches):
        return base_hatches[:n]
    return [base_hatches[i % len(base_hatches)] for i in range(n)]


def apply_visual_encodings(ax, colors: List[str], recommendations: Dict) -> None:
    """
    根据建议自动应用视觉编码
    
    Args:
        ax: matplotlib axes 对象
        colors: 颜色列表
        recommendations: 来自 adapt_colors_for_chart 的建议
    
    Note:
        这个函数需要在绘图之后调用，会尝试修改已有的图表元素
    """
    try:
        from matplotlib.lines import Line2D
        from matplotlib.patches import Rectangle
    except ImportError:
        return
    
    lines = [obj for obj in ax.get_children() if isinstance(obj, Line2D)]
    bars = [obj for obj in ax.patches if isinstance(obj, Rectangle)]
    
    # 应用 markers
    if recommendations.get("add_markers") and lines:
        markers = generate_markers(len(lines))
        for line, marker in zip(lines, markers):
            line.set_marker(marker)
            line.set_markevery(10)  # 每 10 个点显示一个 marker
    
    # 应用线型
    if recommendations.get("add_linestyles") and lines:
        linestyles = generate_linestyles(len(lines))
        for line, style in zip(lines, linestyles):
            line.set_linestyle(style)
    
    # 应用图案
    if recommendations.get("add_hatches") and bars:
        hatches = generate_hatches(len(bars))
        for bar, hatch in zip(bars, hatches):
            bar.set_hatch(hatch)
    
    # 增加线宽
    if recommendations.get("increase_linewidth") and lines:
        for line in lines:
            current_width = line.get_linewidth()
            line.set_linewidth(current_width * 1.5)


if __name__ == "__main__":
    # 测试（需要 matplotlib）
    try:
        import matplotlib.pyplot as plt
        import numpy as np
        
        print("Chart Adaptation Demo")
        print("=" * 70)
        
        # Test 1: 简单线条图
        print("\n[Test 1] Simple line chart:")
        fig, ax = plt.subplots()
        x = np.linspace(0, 10, 100)
        ax.plot(x, np.sin(x))
        ax.plot(x, np.cos(x))
        
        info = detect_chart_type(ax)
        print(f"Type: {info['type']}, Complexity: {info['complexity']}")
        
        colors = ['#E64B35', '#4DBBD5']
        adapted, recs = adapt_colors_for_chart(colors, info)
        print(f"Recommendations: {recs}")
        plt.close()
        
        # Test 2: 复杂线条图
        print("\n[Test 2] Complex line chart:")
        fig, ax = plt.subplots()
        for i in range(12):
            ax.plot(x, np.sin(x + i * 0.5))
        
        info = detect_chart_type(ax)
        print(f"Type: {info['type']}, Complexity: {info['complexity']}")
        
        colors = ['#E64B35', '#4DBBD5', '#00A087', '#3C5488', '#F39B7F']
        adapted, recs = adapt_colors_for_chart(colors, info)
        print(f"Recommendations: {recs}")
        plt.close()
        
        print("\n" + "=" * 70)
        
    except ImportError:
        print("matplotlib not available for testing")

