"""DOCX解析器"""

import io
from typing import Dict, Any, Optional, Union
from docx import Document

from hos_m2f.model.universal_model import UniversalDocumentModel
from hos_m2f.parsers.base_parser import BaseParser


class DOCXParser(BaseParser):
    """DOCX解析器"""
    
    def parse(self, content: Union[str, bytes], options: Optional[Dict[str, Any]] = None) -> UniversalDocumentModel:
        """解析DOCX内容为中间模型
        
        Args:
            content: DOCX内容
            options: 解析选项
            
        Returns:
            UniversalDocumentModel: 通用文档模型
        """
        options = options or {}
        
        # 创建DOCX文档对象
        if isinstance(content, bytes):
            doc = Document(io.BytesIO(content))
        else:
            doc = Document(content)
        
        # 创建通用文档模型
        model = UniversalDocumentModel()
        
        # 1. 提取元数据
        meta = self._extract_meta(doc)
        model.set_meta(meta)
        
        # 2. 生成HTML内容
        html_content = self._generate_html_content(doc, options)
        model.set_html_content(html_content)
        
        # 3. 分析文档结构
        structure = self._analyze_structure(doc)
        for item in structure:
            model.add_structure_item(item)
        
        # 4. 提取语义信息
        semantics = self._extract_semantics(doc)
        model.get_json()["semantics"].update(semantics)
        
        return model
    
    def _extract_meta(self, doc: Document) -> Dict[str, Any]:
        """提取元数据
        
        Args:
            doc: DOCX文档对象
            
        Returns:
            Dict[str, Any]: 元数据字典
        """
        meta = {}
        
        # 尝试从DOCX属性中提取元数据
        try:
            core_properties = doc.core_properties
            if core_properties.title:
                meta["title"] = core_properties.title
            if core_properties.author:
                meta["author"] = core_properties.author
            if core_properties.subject:
                meta["description"] = core_properties.subject
            if core_properties.keywords:
                meta["tags"] = [tag.strip() for tag in core_properties.keywords.split(';')]
            if core_properties.created:
                meta["publish_date"] = core_properties.created.strftime('%Y-%m-%d')
        except Exception as e:
            print(f"Warning: Failed to extract core properties: {e}")
        
        # 如果没有标题，尝试从第一个段落提取
        if not meta.get("title") and len(doc.paragraphs) > 0:
            first_paragraph = doc.paragraphs[0].text.strip()
            if first_paragraph:
                meta["title"] = first_paragraph
        
        return meta
    
    def _generate_html_content(self, doc: Document, options: Dict[str, Any]) -> str:
        """生成HTML内容
        
        Args:
            doc: DOCX文档对象
            options: 生成选项
            
        Returns:
            str: HTML内容
        """
        html_parts = []
        
        # 处理段落
        for paragraph in doc.paragraphs:
            html = self._render_paragraph(paragraph)
            if html:
                html_parts.append(html)
        
        # 处理表格
        for table in doc.tables:
            html = self._render_table(table)
            if html:
                html_parts.append(html)
        
        return "<div class='content'>" + "\n".join(html_parts) + "</div>"
    
    def _render_paragraph(self, paragraph: Any) -> str:
        """渲染段落
        
        Args:
            paragraph: 段落对象
            
        Returns:
            str: HTML内容
        """
        text = paragraph.text.strip()
        if not text:
            return ""
        
        # 检测标题级别
        style_name = paragraph.style.name
        if style_name.startswith('Heading '):
            level = int(style_name.split(' ')[1])
            # 添加格式信息
            format_attrs = self._extract_paragraph_formatting(paragraph)
            if format_attrs:
                return f"<h{level} {format_attrs}>{self._process_run_formatting(paragraph)}</h{level}>"
            return f"<h{level}>{self._process_run_formatting(paragraph)}</h{level}>"
        
        # 检测列表
        if paragraph.style.name.startswith('List '):
            format_attrs = self._extract_paragraph_formatting(paragraph)
            if format_attrs:
                return f"<li {format_attrs}>{self._process_run_formatting(paragraph)}</li>"
            return f"<li>{self._process_run_formatting(paragraph)}</li>"
        
        # 默认段落
        format_attrs = self._extract_paragraph_formatting(paragraph)
        if format_attrs:
            return f"<p {format_attrs}>{self._process_run_formatting(paragraph)}</p>"
        return f"<p>{self._process_run_formatting(paragraph)}</p>"
    
    def _render_table(self, table: Any) -> str:
        """渲染表格
        
        Args:
            table: 表格对象
            
        Returns:
            str: HTML内容
        """
        html = "<table>"
        
        # 处理表头
        if table.rows:
            html += "<thead><tr>"
            for cell in table.rows[0].cells:
                html += f"<th>{cell.text.strip()}</th>"
            html += "</tr></thead>"
        
        # 处理表格内容
        html += "<tbody>"
        for i, row in enumerate(table.rows):
            if i == 0:  # 跳过表头
                continue
            html += "<tr>"
            for cell in row.cells:
                html += f"<td>{cell.text.strip()}</td>"
            html += "</tr>"
        html += "</tbody>"
        
        html += "</table>"
        return html
    
    def _analyze_structure(self, doc: Document) -> list:
        """分析文档结构
        
        Args:
            doc: DOCX文档对象
            
        Returns:
            list: 结构项列表
        """
        structure = []
        
        # 分析段落
        for i, paragraph in enumerate(doc.paragraphs):
            text = paragraph.text.strip()
            if not text:
                continue
            
            style_name = paragraph.style.name
            if style_name.startswith('Heading '):
                level = int(style_name.split(' ')[1])
                structure.append({
                    "type": "heading",
                    "level": level,
                    "title": text,
                    "position": i
                })
            elif paragraph.style.name.startswith('List '):
                list_type = "ordered" if paragraph.style.name.startswith('List Number') else "unordered"
                if not any(item.get('type') == 'list' and item.get('position') == i for item in structure):
                    structure.append({
                        "type": "list",
                        "list_type": list_type,
                        "position": i
                    })
        
        # 分析表格
        for i, table in enumerate(doc.tables):
            structure.append({
                "type": "table",
                "position": i
            })
        
        return structure
    
    def _extract_semantics(self, doc: Document) -> Dict[str, Any]:
        """提取语义信息
        
        Args:
            doc: DOCX文档对象
            
        Returns:
            Dict[str, Any]: 语义信息字典
        """
        semantics = {
            "domain_tag": "",
            "section_id": {},
            "table_type": {},
            "list_type": {}
        }
        
        # 提取章节ID
        section_counter = 1
        for i, paragraph in enumerate(doc.paragraphs):
            style_name = paragraph.style.name
            if style_name.startswith('Heading '):
                level = int(style_name.split(' ')[1])
                text = paragraph.text.strip()
                section_id = f"sec-{section_counter}"
                semantics["section_id"][section_id] = {
                    "title": text,
                    "level": level,
                    "position": i
                }
                section_counter += 1
        
        # 提取列表类型
        list_counter = 0
        for i, paragraph in enumerate(doc.paragraphs):
            style_name = paragraph.style.name
            if style_name.startswith('List '):
                list_type = "ordered" if style_name.startswith('List Number') else "unordered"
                if not any(item.get('type') == 'list' and item.get('position') == i for item in semantics["list_type"]):
                    semantics["list_type"][f"list-{list_counter}"] = list_type
                    list_counter += 1
        
        return semantics
    
    def _extract_paragraph_formatting(self, paragraph: Any) -> str:
        """提取段落格式信息
        
        Args:
            paragraph: 段落对象
            
        Returns:
            str: 格式信息字符串
        """
        format_attrs = []
        
        # 提取对齐方式
        try:
            alignment = paragraph.paragraph_format.alignment
            if alignment:
                # 转换为可读的对齐方式名称
                align_map = {
                    0: 'left',
                    1: 'center',
                    2: 'right',
                    3: 'justify'
                }
                align_name = align_map.get(alignment, 'unknown')
                format_attrs.append(f'style="text-align: {align_name};"')
        except AttributeError:
            pass
        
        # 提取缩进信息
        try:
            if paragraph.paragraph_format.left_indent:
                left_indent = paragraph.paragraph_format.left_indent.inches
                format_attrs.append(f'style="margin-left: {left_indent}in;"')
            if paragraph.paragraph_format.first_line_indent:
                first_indent = paragraph.paragraph_format.first_line_indent.inches
                format_attrs.append(f'style="text-indent: {first_indent}in;"')
        except AttributeError:
            pass
        
        return ' '.join(format_attrs)
    
    def _process_run_formatting(self, paragraph: Any) -> str:
        """处理段落中的文本格式
        
        Args:
            paragraph: 段落对象
            
        Returns:
            str: 格式化后的文本
        """
        formatted_text = []
        
        for run in paragraph.runs:
            run_text = run.text
            if not run_text:
                continue
            
            # 检查格式
            has_formatting = any([
                run.bold,
                run.italic,
                run.underline,
                run.font.color,
                run.font.size,
                run.font.name
            ])
            
            if has_formatting:
                # 开始格式标签
                format_styles = []
                if run.bold:
                    format_styles.append('font-weight: bold;')
                if run.italic:
                    format_styles.append('font-style: italic;')
                if run.underline:
                    format_styles.append('text-decoration: underline;')
                if run.font.color:
                    try:
                        rgb = run.font.color.rgb
                        # 正确处理RGBColor对象
                        try:
                            hex_color = f'#{rgb.red:02x}{rgb.green:02x}{rgb.blue:02x}'
                        except AttributeError:
                            try:
                                hex_color = f'#{rgb.r:02x}{rgb.g:02x}{rgb.b:02x}'
                            except AttributeError:
                                hex_color = None
                        if hex_color:
                            format_styles.append(f'color: {hex_color};')
                    except Exception:
                        pass
                if run.font.size:
                    try:
                        size = run.font.size.pt
                        format_styles.append(f'font-size: {size}pt;')
                    except Exception:
                        pass
                if run.font.name:
                    format_styles.append(f'font-family: "{run.font.name}";')
                
                # 构建格式标签
                if format_styles:
                    style_str = '; '.join(format_styles)
                    formatted_text.append(f'<span style="{style_str}">{run_text}</span>')
                else:
                    formatted_text.append(run_text)
            else:
                formatted_text.append(run_text)
        
        return ''.join(formatted_text)
