"""Markdown到DOCX格式转换器"""

from typing import Any, Optional, Dict
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_UNDERLINE
from docx.enum.style import WD_STYLE_TYPE
from hos_m2f.converters.base_converter import BaseConverter
import mistune


class MDToDOCXConverter(BaseConverter):
    """Markdown到DOCX格式转换器"""
    
    def convert(self, input_content: str, options: Optional[Dict[str, Any]] = None) -> bytes:
        """将Markdown转换为DOCX
        
        Args:
            input_content: Markdown内容
            options: 转换选项
            
        Returns:
            bytes: DOCX文件的二进制数据
        """
        if options is None:
            options = {}
        
        # 创建文档
        doc = Document()
        
        # 设置默认样式
        self._setup_styles(doc)
        
        # 自定义渲染器
        class DOCXRenderer(mistune.HTMLRenderer):
            def __init__(self, doc):
                super().__init__()
                self.doc = doc
                self.current_paragraph = None
                self.list_level = 0
                self.lists = []
            
            def paragraph(self, text):
                if text.strip():
                    p = self.doc.add_paragraph()
                    p.add_run(text)
                return ''
            
            def heading(self, text, level):
                if level == 1:
                    self.doc.add_heading(text, level=0)
                else:
                    self.doc.add_heading(text, level=level-1)
                return ''
            
            def list(self, text, ordered, level, start=None):
                self.list_level += 1
                self.lists.append(ordered)
                return ''
            
            def list_item(self, text, level):
                if text.strip():
                    p = self.doc.add_paragraph(
                        text,
                        style='List Number' if self.lists[level-1] else 'List Bullet'
                    )
                    # 缩进
                    for i in range(level-1):
                        p.paragraph_format.left_indent += Inches(0.5)
                return ''
            
            def list_end(self, level):
                self.list_level -= 1
                if self.lists:
                    self.lists.pop()
                return ''
            
            def table(self, text):
                # 解析Markdown表格并转换为DOCX表格
                try:
                    # 分割表格行
                    rows = text.strip().split('\n')
                    if not rows:
                        return ''
                    
                    # 解析表头
                    header_cells = [cell.strip() for cell in rows[0].split('|') if cell.strip()]
                    if not header_cells:
                        return ''
                    
                    # 创建表格
                    table = self.doc.add_table(rows=1, cols=len(header_cells))
                    table.style = 'Table Grid'
                    
                    # 填充表头
                    header_row = table.rows[0]
                    for i, cell_text in enumerate(header_cells):
                        header_row.cells[i].text = cell_text
                    
                    # 跳过分隔线行
                    if len(rows) > 1 and '---' in rows[1]:
                        data_rows = rows[2:]
                    else:
                        data_rows = rows[1:]
                    
                    # 填充数据行
                    for row in data_rows:
                        cells = [cell.strip() for cell in row.split('|') if cell.strip()]
                        if cells:
                            new_row = table.add_row()
                            for i, cell_text in enumerate(cells):
                                if i < len(new_row.cells):
                                    new_row.cells[i].text = cell_text
                except Exception as e:
                    # 如果解析失败，回退到简单处理
                    self.doc.add_paragraph('Table: ' + text[:100] + '...')
                return ''
            
            def image(self, text, url=None, title=None, alt=None):
                try:
                    # 尝试处理本地和远程图片
                    import os
                    import requests
                    from io import BytesIO
                    
                    # 使用alt作为替代文本
                    if alt is None:
                        alt = text
                    
                    # 检查是否有图片URL
                    if not url:
                        self.doc.add_paragraph(f'Image: {alt}')
                        return ''
                    
                    # 检查是否是本地图片
                    if os.path.exists(url):
                        # 添加本地图片
                        self.doc.add_picture(url)
                    else:
                        # 尝试从网络获取图片
                        response = requests.get(url, timeout=5)
                        if response.status_code == 200:
                            # 添加远程图片
                            image_stream = BytesIO(response.content)
                            self.doc.add_picture(image_stream)
                        else:
                            # 如果获取失败，添加图片描述
                            self.doc.add_paragraph(f'Image: {alt} ({url})')
                except Exception as e:
                    # 如果处理失败，添加图片描述
                    self.doc.add_paragraph(f'Image: {alt or text} ({url or ""})')
                return ''
            
            def link(self, text, url=None, title=None):
                if text and url:
                    # 简化处理，直接添加文本和链接
                    p = self.doc.add_paragraph()
                    run = p.add_run(text)
                    run.font.color.rgb = RGBColor(0, 0, 255)  # 蓝色
                    run.underline = WD_UNDERLINE.SINGLE
                    p.add_run(f' ({url})')
                elif text:
                    p = self.doc.add_paragraph(text)
                elif url:
                    p = self.doc.add_paragraph(url)
                return ''
            
            def emphasis(self, text):
                # 直接添加斜体文本
                p = self.doc.add_paragraph()
                run = p.add_run(text)
                run.italic = True
                return ''
            
            def strong(self, text):
                # 直接添加粗体文本
                p = self.doc.add_paragraph()
                run = p.add_run(text)
                run.bold = True
                return ''
            
            def codespan(self, text):
                p = self.doc.add_paragraph()
                run = p.add_run(text)
                run.font.name = 'Courier New'
                return ''
            
            def block_code(self, code, info=None):
                # 处理Mermaid图表
                if info == 'mermaid':
                    try:
                        # 尝试渲染Mermaid图表为图片
                        mermaid_image = self._render_mermaid(code)
                        if mermaid_image:
                            # 添加图片
                            self.doc.add_picture(mermaid_image)
                            return ''
                        else:
                            # 如果渲染失败，添加代码块
                            p = self.doc.add_paragraph('Mermaid Chart:')
                            p = self.doc.add_paragraph(code)
                            p.paragraph_format.left_indent = Inches(0.5)
                            return ''
                    except Exception as e:
                        # 如果处理失败，添加代码块
                        p = self.doc.add_paragraph('Mermaid Chart:')
                        p = self.doc.add_paragraph(code)
                        p.paragraph_format.left_indent = Inches(0.5)
                        return ''
                else:
                    # 处理普通代码块
                    p = self.doc.add_paragraph()
                    run = p.add_run(code)
                    run.font.name = 'Courier New'
                    p.paragraph_format.left_indent = Inches(0.5)
                    return ''
            
            def _render_mermaid(self, mermaid_code):
                """渲染Mermaid图表为图片"""
                # 简化处理，实际项目中需要使用mermaid-cli或其他工具
                # 这里返回None，回退到显示代码块
                return None
        
        # 渲染Markdown
        renderer = DOCXRenderer(doc)
        markdown = mistune.create_markdown(renderer=renderer)
        markdown(input_content)
        
        # 保存为二进制数据
        import io
        output = io.BytesIO()
        doc.save(output)
        output.seek(0)
        
        return output.getvalue()
    
    def _setup_styles(self, doc):
        """设置文档样式"""
        styles = doc.styles
        
        # 设置正文样式
        normal_style = styles['Normal']
        font = normal_style.font
        font.name = 'Microsoft YaHei'
        font.size = Pt(12)
        
        # 设置标题样式
        for i in range(1, 6):
            heading_style = styles[f'Heading {i}']
            font = heading_style.font
            font.name = 'Microsoft YaHei'
            font.size = Pt(14 + (6 - i) * 2)
            font.bold = True
    
    def get_supported_formats(self) -> tuple:
        """获取支持的格式"""
        return ('markdown', 'docx')
