"""XML模板化模块"""

from typing import Dict, List, Tuple
from lxml import etree as ET


class XMLTemplater:
    """XML模板化工具
    
    功能：
    1. 将XML中的实际内容转换为变量占位符
    2. 生成变量映射表
    3. 支持两种模板化方法：
       - 手动字段指定
       - 自动字段识别
    """
    
    def __init__(self):
        """初始化模板器"""
        pass
    
    def template_by_fields(self, xml_content: str, fields: List[str]) -> Tuple[str, Dict[str, str]]:
        """根据指定字段进行模板化
        
        Args:
            xml_content: XML内容字符串
            fields: 需要模板化的字段列表
            
        Returns:
            Tuple[str, Dict[str, str]]: (模板XML, 变量映射表)
        """
        # 解析XML
        try:
            # 尝试直接解析
            root = ET.fromstring(xml_content)
        except ValueError:
            # 如果是Unicode字符串带有编码声明，转换为字节串
            if isinstance(xml_content, str):
                xml_content = xml_content.encode('utf-8')
            root = ET.fromstring(xml_content)
        
        # 生成变量映射表
        variable_map = {}
        
        # 处理每个字段
        for field in fields:
            # 使用XPath查找所有匹配的元素
            elements = root.xpath(f".//{field}")
            for elem in elements:
                if elem.text and elem.text.strip():
                    # 保存原始值到映射表
                    variable_map[field] = elem.text.strip()
                    # 替换为变量占位符
                    elem.text = f"{{{{{field}}}}}"
        
        # 生成模板XML
        template_xml = ET.tostring(root, pretty_print=True, encoding="unicode")
        
        return template_xml, variable_map
    
    def template_auto(self, xml_content: str) -> Tuple[str, Dict[str, str]]:
        """自动识别文本节点并进行模板化
        
        Args:
            xml_content: XML内容字符串
            
        Returns:
            Tuple[str, Dict[str, str]]: (模板XML, 变量映射表)
        """
        # 解析XML
        try:
            # 尝试直接解析
            root = ET.fromstring(xml_content)
        except ValueError:
            # 如果是Unicode字符串带有编码声明，转换为字节串
            if isinstance(xml_content, str):
                xml_content = xml_content.encode('utf-8')
            root = ET.fromstring(xml_content)
        
        # 生成变量映射表
        variable_map = {}
        
        # 遍历所有元素
        counter = 1
        for elem in root.iter():
            if elem.text and elem.text.strip():
                # 生成变量名
                variable_name = f"field_{counter}"
                # 保存原始值到映射表
                variable_map[variable_name] = elem.text.strip()
                # 替换为变量占位符
                elem.text = f"{{{{{variable_name}}}}}"
                counter += 1
        
        # 生成模板XML
        template_xml = ET.tostring(root, pretty_print=True, encoding="unicode")
        
        return template_xml, variable_map
    
    def template_from_file(self, xml_file: str, method: str = 'auto', fields: List[str] = None) -> Tuple[str, Dict[str, str]]:
        """从文件进行模板化
        
        Args:
            xml_file: XML文件路径
            method: 模板化方法 ('auto' 或 'fields')
            fields: 当method为'fields'时的字段列表
            
        Returns:
            Tuple[str, Dict[str, str]]: (模板XML, 变量映射表)
        """
        # 读取XML文件，尝试不同编码
        encodings = ['utf-8', 'gbk', 'ansi']
        xml_content = None
        
        for encoding in encodings:
            try:
                with open(xml_file, 'r', encoding=encoding) as f:
                    xml_content = f.read()
                break
            except UnicodeDecodeError:
                continue
        
        if xml_content is None:
            raise Exception("无法读取文件：所有编码尝试都失败")
        
        # 根据方法选择模板化方式
        if method == 'fields' and fields:
            return self.template_by_fields(xml_content, fields)
        else:
            return self.template_auto(xml_content)
    
    def save_template(self, template_xml: str, template_file: str) -> None:
        """保存模板到文件
        
        Args:
            template_xml: 模板XML内容
            template_file: 保存路径
        """
        with open(template_file, 'w', encoding='utf-8') as f:
            f.write(template_xml)
    
    def save_variable_map(self, variable_map: Dict[str, str], map_file: str) -> None:
        """保存变量映射表到文件
        
        Args:
            variable_map: 变量映射表
            map_file: 保存路径
        """
        import json
        with open(map_file, 'w', encoding='utf-8') as f:
            json.dump(variable_map, f, ensure_ascii=False, indent=2)
