#!/usr/bin/env python3
"""
PDF 导出脚本 - pdf-exporter skill
支持完整 Markdown 格式：标题、段落、加粗、斜体、行内代码、代码块、
有序/无序列表（含嵌套）、表格、水平线。

用法: python3 export_pdf.py --title "标题" --content "内容" --output "输出路径"
"""
import sys
import os
import re
import argparse

sys.path.insert(0, '/workspace/.local/lib/python3.11/site-packages')

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, KeepTogether
from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont


# ─────────────────────────────────────────────────────────────────────────────
# Font registration for Chinese support
# ─────────────────────────────────────────────────────────────────────────────

def register_chinese_fonts():
    """Register Chinese fonts for PDF generation."""
    font_paths = [
        # Common Linux Chinese fonts
        '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
        '/usr/share/fonts/truetype/wqy/wqy-microhei.ttc',
        '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
        '/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc',
        '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
        # macOS fonts
        '/System/Library/Fonts/PingFang.ttc',
        '/Library/Fonts/Arial Unicode.ttf',
        # Windows fonts
        'C:/Windows/Fonts/simhei.ttf',
        'C:/Windows/Fonts/simsun.ttc',
        'C:/Windows/Fonts/msyh.ttc',
        'C:/Windows/Fonts/msyhbd.ttc',
    ]
    
    registered = []
    for font_path in font_paths:
        if os.path.exists(font_path):
            try:
                font_name = os.path.basename(font_path).replace('.ttc', '').replace('.ttf', '')
                pdfmetrics.registerFont(TTFont(font_name, font_path))
                registered.append(font_name)
            except:
                pass
    
    return registered[0] if registered else 'Helvetica'


# ─────────────────────────────────────────────────────────────────────────────
# Markdown parsing helpers
# ─────────────────────────────────────────────────────────────────────────────

def parse_inline_markdown(text):
    """Parse inline markdown (**bold**, *italic*, `code`) and return ReportLab formatted text."""
    # Escape XML special characters
    text = text.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
    
    # Pattern order matters: bold-italic first, then bold, then italic, then code
    patterns = [
        (r'\*\*\*(.+?)\*\*\*', r'<b><i>\1</i></b>'),   # bold-italic
        (r'\*\*(.+?)\*\*', r'<b>\1</b>'),              # bold
        (r'__(.+?)__', r'<b>\1</b>'),                   # bold (alt)
        (r'\*(.+?)\*', r'<i>\1</i>'),                  # italic
        (r'_(.+?)_', r'<i>\1</i>'),                     # italic (alt)
        (r'`(.+?)`', r'<font name="Courier" size="9" color="#C7254E">\1</font>'),  # inline code
    ]
    
    for pattern, replacement in patterns:
        text = re.sub(pattern, replacement, text)
    
    return text


def is_table_separator(line):
    """Check if line is a markdown table separator like |---|---|"""
    stripped = line.strip()
    if not stripped.startswith('|'):
        return False
    return bool(re.match(r'^[\|\s\-:]+$', stripped))


def parse_table_row(line):
    """Parse a markdown table row into a list of cell strings."""
    line = line.strip()
    if line.startswith('|'):
        line = line[1:]
    if line.endswith('|'):
        line = line[:-1]
    return [cell.strip() for cell in line.split('|')]


# ─────────────────────────────────────────────────────────────────────────────
# Main export function
# ─────────────────────────────────────────────────────────────────────────────

def export_pdf(title: str, content: str, output_path: str) -> str:
    # Register fonts and get Chinese font name
    chinese_font = register_chinese_fonts()
    
    # Create document
    doc = SimpleDocTemplate(
        output_path,
        pagesize=A4,
        rightMargin=2*cm,
        leftMargin=2*cm,
        topMargin=2*cm,
        bottomMargin=2*cm
    )
    
    # Define styles
    styles = getSampleStyleSheet()
    
    # Custom styles with Chinese font support
    title_style = ParagraphStyle(
        'CustomTitle',
        parent=styles['Title'],
        fontName=chinese_font,
        fontSize=20,
        alignment=TA_CENTER,
        spaceAfter=30,
        leading=24
    )
    
    heading1_style = ParagraphStyle(
        'CustomHeading1',
        parent=styles['Heading1'],
        fontName=chinese_font,
        fontSize=16,
        spaceBefore=20,
        spaceAfter=10,
        leading=20
    )
    
    heading2_style = ParagraphStyle(
        'CustomHeading2',
        parent=styles['Heading2'],
        fontName=chinese_font,
        fontSize=14,
        spaceBefore=16,
        spaceAfter=8,
        leading=18
    )
    
    heading3_style = ParagraphStyle(
        'CustomHeading3',
        parent=styles['Heading3'],
        fontName=chinese_font,
        fontSize=12,
        spaceBefore=12,
        spaceAfter=6,
        leading=16
    )
    
    normal_style = ParagraphStyle(
        'CustomNormal',
        parent=styles['Normal'],
        fontName=chinese_font,
        fontSize=11,
        alignment=TA_JUSTIFY,
        leading=16,
        spaceAfter=8
    )
    
    code_style = ParagraphStyle(
        'CustomCode',
        parent=styles['Code'],
        fontName='Courier',
        fontSize=9,
        leftIndent=20,
        rightIndent=20,
        spaceBefore=8,
        spaceAfter=8,
        leading=12
    )
    
    bullet_style = ParagraphStyle(
        'CustomBullet',
        parent=styles['Normal'],
        fontName=chinese_font,
        fontSize=11,
        leftIndent=30,
        bulletIndent=15,
        leading=16,
        spaceAfter=4
    )
    
    bullet2_style = ParagraphStyle(
        'CustomBullet2',
        parent=styles['Normal'],
        fontName=chinese_font,
        fontSize=11,
        leftIndent=50,
        bulletIndent=35,
        leading=16,
        spaceAfter=4
    )
    
    number_style = ParagraphStyle(
        'CustomNumber',
        parent=styles['Normal'],
        fontName=chinese_font,
        fontSize=11,
        leftIndent=30,
        bulletIndent=15,
        leading=16,
        spaceAfter=4
    )
    
    quote_style = ParagraphStyle(
        'CustomQuote',
        parent=styles['Normal'],
        fontName=chinese_font,
        fontSize=11,
        leftIndent=30,
        rightIndent=30,
        textColor=colors.grey,
        leading=16,
        spaceAfter=8
    )
    
    footer_style = ParagraphStyle(
        'CustomFooter',
        parent=styles['Normal'],
        fontName=chinese_font,
        fontSize=9,
        textColor=colors.grey,
        alignment=TA_CENTER,
        spaceBefore=30
    )
    
    # Build document content
    story = []
    
    # Add title
    story.append(Paragraph(title, title_style))
    story.append(Spacer(1, 20))
    
    lines = content.split('\n')
    i = 0
    
    while i < len(lines):
        line = lines[i]
        raw = line.rstrip()
        
        # ── Fenced code block ────────────────────────────────────────────────
        if raw.startswith('```'):
            lang = raw[3:].strip()
            code_lines = []
            i += 1
            while i < len(lines) and not lines[i].rstrip().startswith('```'):
                code_lines.append(lines[i].rstrip('\n'))
                i += 1
            code_text = '\n'.join(code_lines)
            # Escape XML special characters for code
            code_text = code_text.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
            story.append(Paragraph(f'<font name="Courier" size="9" backColor="#F5F5F5">{code_text}</font>', code_style))
            i += 1
            continue
        
        # ── Horizontal rule ──────────────────────────────────────────────────
        if re.match(r'^(\-{3,}|\*{3,}|_{3,})\s*$', raw):
            story.append(Spacer(1, 10))
            story.append(Table([['']], colWidths=[15*cm], style=TableStyle([
                ('LINEABOVE', (0, 0), (-1, 0), 1, colors.grey),
            ])))
            story.append(Spacer(1, 10))
            i += 1
            continue
        
        # ── Headings ─────────────────────────────────────────────────────────
        m = re.match(r'^(#{1,6})\s+(.*)', raw)
        if m:
            level = min(len(m.group(1)), 6)
            heading_text = parse_inline_markdown(m.group(2).strip())
            if level == 1:
                story.append(Paragraph(heading_text, heading1_style))
            elif level == 2:
                story.append(Paragraph(heading_text, heading2_style))
            else:
                story.append(Paragraph(heading_text, heading3_style))
            i += 1
            continue
        
        # ── Table ────────────────────────────────────────────────────────────
        if raw.startswith('|') and '|' in raw[1:]:
            table_rows = []
            while i < len(lines) and lines[i].strip().startswith('|'):
                if not is_table_separator(lines[i]):
                    table_rows.append(parse_table_row(lines[i]))
                i += 1
            
            if table_rows:
                # Convert to ReportLab table format
                col_count = max(len(r) for r in table_rows)
                data = []
                for row_idx, row_data in enumerate(table_rows):
                    formatted_row = []
                    for cell_text in row_data:
                        formatted_cell = parse_inline_markdown(cell_text)
                        formatted_row.append(Paragraph(formatted_cell, normal_style))
                    # Pad row if needed
                    while len(formatted_row) < col_count:
                        formatted_row.append('')
                    data.append(formatted_row)
                
                # Calculate column widths
                col_width = 15*cm / col_count
                col_widths = [col_width] * col_count
                
                table = Table(data, colWidths=col_widths)
                table_style = TableStyle([
                    ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
                    ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                    ('PADDING', (0, 0), (-1, -1), 6),
                ])
                # Header row style
                if len(data) > 0:
                    table_style.add('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey)
                    table_style.add('FONTNAME', (0, 0), (-1, 0), chinese_font)
                table.setStyle(table_style)
                story.append(Spacer(1, 8))
                story.append(table)
                story.append(Spacer(1, 8))
            continue
        
        # ── Unordered list ───────────────────────────────────────────────────
        m = re.match(r'^(\s*)([-*+])\s+(.*)', raw)
        if m:
            indent = len(m.group(1))
            item_text = parse_inline_markdown(m.group(3))
            if indent >= 2:
                story.append(Paragraph(f'• {item_text}', bullet2_style))
            else:
                story.append(Paragraph(f'• {item_text}', bullet_style))
            i += 1
            continue
        
        # ── Ordered list ─────────────────────────────────────────────────────
        m = re.match(r'^(\s*)\d+[.)]\s+(.*)', raw)
        if m:
            indent = len(m.group(1))
            item_text = parse_inline_markdown(m.group(2))
            story.append(Paragraph(item_text, number_style))
            i += 1
            continue
        
        # ── Blockquote ───────────────────────────────────────────────────────
        if raw.startswith('> '):
            quote_text = parse_inline_markdown(raw[2:])
            story.append(Paragraph(quote_text, quote_style))
            i += 1
            continue
        
        # ── Empty line ───────────────────────────────────────────────────────
        if raw.strip() == '':
            story.append(Spacer(1, 8))
            i += 1
            continue
        
        # ── Normal paragraph ─────────────────────────────────────────────────
        para_text = parse_inline_markdown(raw)
        story.append(Paragraph(para_text, normal_style))
        i += 1
    
    # Add footer
    story.append(Spacer(1, 30))
    story.append(Paragraph('以上内容由 ECclaw 生成', footer_style))
    
    # Ensure output directory exists
    os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
    
    # Build PDF
    doc.build(story)
    return output_path


# ─────────────────────────────────────────────────────────────────────────────
# CLI
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='导出 PDF 文档（支持完整 Markdown）')
    parser.add_argument('--title',   required=True, help='文档标题')
    parser.add_argument('--content', required=True, help='文档正文（Markdown 格式）')
    parser.add_argument('--output',  required=True, help='输出 .pdf 文件路径')
    args = parser.parse_args()

    output = export_pdf(args.title, args.content, args.output)
    print(f'output_path: {output}')
    print('PDF 文档导出成功')
