"""
坐标轴 XML 操作模块

负责创建、提取和优化坐标轴元素。
"""

from lxml import etree
from typing import Tuple

from ..oxml_ns import NAMESPACES


def extract_axis_ids(plotArea) -> Tuple[int, int]:
    """
    提取现有坐标轴的 ID
    
    Args:
        plotArea: 绘图区元素 (lxml Element)
        
    Returns:
        (cat_ax_id, val_ax_id) 元组
        
    Raises:
        ValueError: 如果无法找到坐标轴 ID
    """
    # python-pptx 的 BaseOxmlElement.xpath() 已经注册了命名空间
    cat_ax_elements = plotArea.xpath('.//c:catAx/c:axId')
    val_ax_elements = plotArea.xpath('.//c:valAx/c:axId')
    
    if not cat_ax_elements or not val_ax_elements:
        raise ValueError("无法找到现有坐标轴 ID")
    
    cat_ax_id = int(cat_ax_elements[0].get('val'))
    val_ax_id = int(val_ax_elements[0].get('val'))
    
    return cat_ax_id, val_ax_id


def create_value_axis(
    plotArea,
    ax_id: int,
    cross_ax_id: int,
    position: str = 'r',
    tick_label_position: str = 'high',
    crosses_at: str = 'max',
) -> int:
    """
    创建一个新的值轴 (Y轴)
    
    Args:
        plotArea: 绘图区元素 (lxml Element)
        ax_id: 新轴的 ID
        cross_ax_id: 交叉轴的 ID（通常是分类轴）
        position: 轴位置 ('l'=左, 'r'=右, 't'=顶, 'b'=底)
        tick_label_position: 标签位置 ('low'=左/底, 'high'=右/顶, 'nextTo'=靠近轴)
        crosses_at: 交叉位置 ('min'=最小值/左边, 'max'=最大值/右边)
        
    Returns:
        创建的轴 ID
        
    Notes:
        - 严格按照 OOXML 规范 (ISO/IEC 29500-1:2016) 的元素顺序
        - 'low' 和 'high' 用于双轴图，确保标签不重叠
        - crosses_at='min' 让轴线在图表左边，'max' 让轴线在图表右边
    """
    # 创建值轴元素
    valAx = etree.SubElement(plotArea, f"{{{NAMESPACES['c']}}}valAx")
    
    # ⭐ 严格按照 OOXML 规范顺序添加子元素
    
    # 1. axId (轴 ID) - 必需
    axId_elem = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}axId")
    axId_elem.set('val', str(ax_id))
    
    # 2. scaling (缩放) - 必需
    scaling = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}scaling")
    orientation = etree.SubElement(scaling, f"{{{NAMESPACES['c']}}}orientation")
    orientation.set('val', 'minMax')
    
    # 3. delete (是否隐藏) - 必需
    delete = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}delete")
    delete.set('val', '0')
    
    # 4. axPos (轴位置) - 必需
    axPos = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}axPos")
    axPos.set('val', position)
    
    # 5. majorGridlines (主网格线) - 可选
    # 次轴通常不显示网格线，避免与主轴重叠
    # 如果需要，调用方可以手动添加
    
    # 6. numFmt (数字格式) - 可选
    numFmt = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}numFmt")
    numFmt.set('formatCode', 'General')
    numFmt.set('sourceLinked', '0')
    
    # 7. majorTickMark (主刻度线) - 可选
    majorTickMark = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}majorTickMark")
    majorTickMark.set('val', 'out')
    
    # 8. minorTickMark (次刻度线) - 可选
    minorTickMark = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}minorTickMark")
    minorTickMark.set('val', 'none')
    
    # 9. tickLblPos (标签位置) - 可选
    tickLblPos = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}tickLblPos")
    tickLblPos.set('val', tick_label_position)
    
    # 10. crossAx (交叉轴 ID) - 必需
    crossAx = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}crossAx")
    crossAx.set('val', str(cross_ax_id))
    
    # 11. crosses (交叉方式) - 可选
    # ⭐ 关键修复：根据 crosses_at 参数决定交叉位置
    # 'min' = 在最小值（左边）交叉，'max' = 在最大值（右边）交叉
    crosses = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}crosses")
    crosses.set('val', crosses_at)
    
    # 12. crossBetween (交叉位置) - 可选
    crossBetween = etree.SubElement(valAx, f"{{{NAMESPACES['c']}}}crossBetween")
    crossBetween.set('val', 'between')
    
    return ax_id


def optimize_axis_labels(
    plotArea,
    ax_id: int,
    tick_label_position: str = 'low',
    crosses_at: str = 'min',
    remove_gridlines: bool = True,
):
    """
    优化现有轴的标签位置和交叉位置
    
    Args:
        plotArea: 绘图区元素
        ax_id: 要优化的轴 ID
        tick_label_position: 标签位置 ('low'=左/底, 'high'=右/顶)
        crosses_at: 交叉位置 ('min'=最小值/左边, 'max'=最大值/右边)
        remove_gridlines: 是否移除网格线（默认移除）
        
    Notes:
        主要用于优化主值轴，使其与次值轴协调
        crosses_at='min' 让主轴线在图表左边，'max' 让次轴线在图表右边
    """
    # 查找指定的值轴
    val_ax_elements = plotArea.xpath(f'.//c:valAx[c:axId[@val="{ax_id}"]]')
    if not val_ax_elements:
        return  # 轴不存在，跳过
    
    val_ax = val_ax_elements[0]
    
    # ⭐ 设置 crosses 位置
    crosses_elements = val_ax.xpath('./c:crosses')
    if crosses_elements:
        crosses_elements[0].set('val', crosses_at)
    
    # 设置标签位置
    tickLblPos_elements = val_ax.xpath('./c:tickLblPos')
    if tickLblPos_elements:
        tickLblPos_elements[0].set('val', tick_label_position)
    else:
        # 如果不存在，创建一个
        tickLblPos = etree.Element(f"{{{NAMESPACES['c']}}}tickLblPos")
        tickLblPos.set('val', tick_label_position)
        # 插入到 crossAx 之前（保持正确顺序）
        cross_ax_elements = val_ax.xpath('./c:crossAx')
        if cross_ax_elements:
            cross_ax_elements[0].addprevious(tickLblPos)
    
    # ⭐ 移除网格线（取消内部横框）
    if remove_gridlines:
        gridlines = val_ax.xpath('./c:majorGridlines')
        for gridline in gridlines:
            val_ax.remove(gridline)
            print(f"  → 已移除主值轴网格线")


def optimize_category_axis(
    plotArea,
    cat_ax_id: int,
    remove_tick_marks: bool = True,
):
    """
    优化分类轴（X轴）的显示
    
    Args:
        plotArea: 绘图区元素
        cat_ax_id: 分类轴 ID
        remove_tick_marks: 是否移除主刻度线（默认移除，即取消日期间的小竖线）
        
    Notes:
        用于清理分类轴的视觉元素，让图表更简洁
    """
    # 查找分类轴
    cat_ax_elements = plotArea.xpath(f'.//c:catAx[c:axId[@val="{cat_ax_id}"]]')
    if not cat_ax_elements:
        return  # 轴不存在，跳过
    
    cat_ax = cat_ax_elements[0]
    
    # ⭐ 移除或设置主刻度线为 'none'（取消日期间的小竖线）
    if remove_tick_marks:
        majorTickMark_elements = cat_ax.xpath('./c:majorTickMark')
        if majorTickMark_elements:
            # 修改为 'none' 而不是删除元素
            majorTickMark_elements[0].set('val', 'none')
            print(f"  → 已移除分类轴主刻度线（日期间的小竖线）")
        
        # 同时也设置次刻度线为 'none'
        minorTickMark_elements = cat_ax.xpath('./c:minorTickMark')
        if minorTickMark_elements:
            minorTickMark_elements[0].set('val', 'none')

