#!/usr/bin/env python3
"""
修復長照倫理治理稿件中的公式圖片
用 matplotlib 渲染高清公式，替換 docx 中的低解析度 PNG
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib import rcParams
from docx import Document
from docx.oxml.ns import qn
import io
import os

# 設定
rcParams['mathtext.fontset'] = 'cm'
rcParams['font.family'] = 'serif'

SRC = '/Users/lingochen/Desktop/長照倫理治理稿件.docx'
DST = '/Users/lingochen/Desktop/長照倫理治理稿件_公式修復版.docx'

def render_formula(latex, fontsize=16, dpi=300, width=8, height=0.7):
    """渲染 LaTeX 公式為 PNG bytes"""
    fig, ax = plt.subplots(figsize=(width, height))
    ax.text(0.5, 0.5, f'${latex}$', fontsize=fontsize,
            ha='center', va='center', transform=ax.transAxes,
            color='black')
    ax.axis('off')
    buf = io.BytesIO()
    fig.savefig(buf, format='png', dpi=dpi, bbox_inches='tight',
                pad_inches=0.05, facecolor='white', edgecolor='none')
    plt.close(fig)
    buf.seek(0)
    return buf.read()

def get_image_rel_ids(para):
    """取得段落中所有圖片的 relationship ID"""
    rids = []
    for run in para.runs:
        drawings = run._element.findall(qn('w:drawing'))
        for drawing in drawings:
            blips = drawing.findall('.//' + qn('a:blip'))
            for blip in blips:
                rid = blip.get(qn('r:embed'))
                if rid:
                    rids.append((blip, rid))
    return rids

def replace_first_image(para, img_bytes):
    """替換段落中的第一張圖片"""
    for run in para.runs:
        drawings = run._element.findall(qn('w:drawing'))
        for drawing in drawings:
            blips = drawing.findall('.//' + qn('a:blip'))
            for blip in blips:
                rid = blip.get(qn('r:embed'))
                if rid:
                    # 建立新圖片 part
                    from docx.opc.part import Part
                    from docx.opc.packuri import PackURI
                    import hashlib
                    
                    img_name = f'formula_{hashlib.md5(img_bytes).hexdigest()[:8]}.png'
                    img_part = Part(
                        PackURI(f'/word/media/{img_name}'),
                        'image/png',
                        img_bytes,
                        para.part.package
                    )
                    
                    # 新增 relationship
                    new_rId = para.part.relate_to(
                        img_part, 
                        'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'
                    )
                    
                    # 更新 blip 引用
                    blip.set(qn('r:embed'), new_rId)
                    
                    # 調整圖片尺寸
                    extent = drawing.find('.//' + qn('wp:extent'))
                    if extent is not None:
                        extent.set('cx', '5400000')  # 約 14.2cm
                        extent.set('cy', '540000')   # 約 1.4cm
                    
                    return True
    return False

# === 公式定義 ===
# 根據段落上下文推斷的公式
formulas = {
    # P38: Z = [z_ij] 直接影響矩陣
    38: r'Z = [z_{ij}]_{n \times n}',
    
    # P39: α = 1 / max row sum 正規化
    39: r'\alpha = \frac{1}{\max_{i} \sum_{j=1}^{n} z_{ij}}',
    
    # P40: T = X(I - X)^{-1} 總影響關係矩陣
    40: r'T = X(I - X)^{-1}',
    
    # P41: D+R 和 D-R 重要度與關聯度
    41: r'D_i + R_i \;\mathrm{(Prominence)} \qquad D_i - R_i \;\mathrm{(Causality)}',
    
    # P62: Borda 分數公式
    62: r'B_i = (n-1) \cdot r_i^D + (n-1) \cdot r_i^W',
    
    # P63: 排序加總公式
    63: r'S_i = r_i^D + r_i^W \qquad B_i = (n-1) \cdot S_i',
}

# === 主程式 ===
print("📄 開始修復公式...")
doc = Document(SRC)

for para_idx, latex in formulas.items():
    para = doc.paragraphs[para_idx]
    
    # 確認段落有圖片
    rids = get_image_rel_ids(para)
    if not rids:
        print(f"⚠️ P{para_idx}: 無圖片，跳過")
        continue
    
    print(f"\n📐 P{para_idx}: 渲染公式...")
    print(f"   LaTeX: {latex}")
    
    # 渲染公式
    img_bytes = render_formula(latex, fontsize=18, dpi=300, width=10, height=1.0)
    
    # 儲存供檢查
    with open(f'/Users/lingochen/Desktop/formula_new_{para_idx}.png', 'wb') as f:
        f.write(img_bytes)
    print(f"   ✅ 已儲存 formula_new_{para_idx}.png ({len(img_bytes)} bytes)")
    
    # 替換 docx 中的圖片
    ok = replace_first_image(para, img_bytes)
    if ok:
        print(f"   ✅ 已替換 P{para_idx} 的圖片")
    else:
        print(f"   ❌ P{para_idx} 替換失敗")

# 儲存
doc.save(DST)
print(f"\n✅ 已儲存修復版：{DST}")
print("📊 P95（圖 5）保留不動")
