"""
Generate bilingual.dj for 佛教徒的人生态度.
Source: Chinese from DOCX manuscript.
Target: English from PDF typeset.

Strategy: find each DOCX English paragraph in PDF body, extract
the PDF text region for that paragraph using position boundaries.
"""
import re, subprocess, os

DOCX = "/home/user/documents/mpi/translate-files/佛教徒的人生态度/定稿 佛教徒的人生态度 善鑫慧炬照禅道靖妙一观轩慈德20260527.docx"
PDF = "/home/user/documents/mpi/translate-files/佛教徒的人生态度/0607-二排-果澄-佛教徒的人生态度-一校-多人-0607.pdf"
OUT_DIR = "/home/user/documents/mpi/translate-files/佛教徒的人生态度"


def has_cjk(s):
    return any('\u4e00' <= c <= '\u9fff' for c in s)


def pandoc(path):
    r = subprocess.run(['pandoc', path, '-f', 'docx', '-t', 'plain', '--wrap=none'],
                       capture_output=True, text=True)
    return r.stdout


def extract_docx_pairs(text):
    """Return [(cn_para, en_para), ...] from body onwards."""
    lines = text.split('\n')
    body_start = None
    for i, l in enumerate(lines):
        if '生活在这个世间' in l:
            body_start = i
            break
    pairs = []
    i = body_start
    while i < len(lines):
        cn = lines[i].strip()
        if not cn or not has_cjk(cn):
            i += 1
            continue
        en = ''
        if i + 2 < len(lines) and lines[i+1].strip() == '':
            ec = lines[i+2].strip()
            if ec and not has_cjk(ec):
                en = ec
                i += 3
            else:
                i += 1
        else:
            i += 1
            continue
        pairs.append((cn, en))
    return pairs


def extract_pdf_body(text):
    """Return cleaned PDF body string."""
    lines = text.split('\n')
    body_start = None
    for i, l in enumerate(lines):
        if 'iving in this world' in l.strip():
            body_start = i
            break
    slug_re = re.compile(r'佛教徒的人生态度.*indd \d+')
    hdr_re = re.compile(r'^(The Life Attitudes of Buddhists|The Mindful Peace Academy Collection)$')
    pn_re = re.compile(r'^\d{1,3}$')
    
    tl = []
    for i in range(body_start, len(lines)):
        s = lines[i].strip()
        if not s or s == '\x0c':
            continue
        if slug_re.search(s) or hdr_re.match(s) or pn_re.match(s):
            continue
        tl.append(s)
    
    # Join hyphenation breaks — handle consecutive breaks
    joined = []
    i = 0
    while i < len(tl):
        line = tl[i].rstrip()
        if line.endswith('-') and i + 1 < len(tl):
            n = tl[i+1].lstrip()
            if n and n[0].islower():
                merged = line[:-1] + n
                # Check if MORE consecutive breaks follow
                j = i + 2
                while j < len(tl) and merged.rstrip().endswith('-'):
                    nn = tl[j].lstrip()
                    if nn and nn[0].islower():
                        merged = merged.rstrip()[:-1] + nn
                        j += 1
                    else:
                        break
                joined.append(merged)
                i = j
                continue
        joined.append(line)
        i += 1
    
    body = ' '.join(joined)
    body = re.sub(r'\s+', ' ', body).strip()
    body = body.replace('L iving', 'Living')
    return body


def norm(s):
    s = re.sub(r'\s+', ' ', s).strip().lower()
    s = s.replace('\u201c', '"').replace('\u201d', '"')
    s = s.replace('\u2018', "'").replace('\u2019', "'")
    return s


def find_positions(pairs, pdf_body):
    """For each DOCX English para, find start position in PDF body.
    Returns list of (start_pos or None, matched_text or None).
    """
    positions = []
    last_pos = 0
    for cn, en in pairs:
        needle = norm(en)
        haystack = norm(pdf_body[last_pos:])
        
        # Try full match
        idx = haystack.find(needle)
        if idx < 0:
            # Try first 80 chars
            key = needle[:80]
            idx = haystack.find(key)
        if idx < 0:
            # Try first 40 chars
            key = needle[:40]
            idx = haystack.find(key)
        if idx < 0:
            # Try first 25 chars
            key = needle[:25]
            idx = haystack.find(key)
        
        if idx >= 0:
            pos = last_pos + idx
            positions.append(pos)
            last_pos = pos + max(len(needle), 30)
        else:
            positions.append(None)
    return positions


def extract_segments(pdf_body, positions):
    """For each position, extract the PDF text region.
    Region extends from positions[i] to positions[i+1] (or end),
    trimmed to avoid bleeding into the next paragraph.
    """
    segments = []
    for i, pos in enumerate(positions):
        if pos is None:
            segments.append(None)
            continue
        
        start = pos
        end = len(pdf_body)
        for j in range(i + 1, len(positions)):
            if positions[j] is not None:
                end = positions[j]
                break
        
        raw = pdf_body[start:end].strip()
        
        # Trim: if raw contains what looks like the NEXT paragraph's heading,
        # cut at the last sentence boundary before it.
        # Headings match patterns like: "I Passive", "1) Expressions", "1. The Definitions"
        heading_pattern = re.compile(
            r'\s+(?=[IVX]+\.?\s+[A-Z]'            # Roman numeral chapter
            r'|\d+\)\s+[A-Z]'                       # 1) Sub-heading
            r'|\(\d+\)\s+[A-Z]'                     # (1) Sub-heading
            r'|\d+\.\s+[A-Z][a-z]+.*?(?:Passive|Pessimism|Abstinence|Focus|Benefit|Transcending|Love|Adapting|Conclusion|Desire|Being|What|How|The|Buddhism|Set|Free|A Middle)'  # Numbered heading
            r')'
        )
        m = heading_pattern.search(raw)
        if m:
            # Cut before this heading
            raw = raw[:m.start()].strip()
        
        segments.append(raw)
    return segments


def generate(pairs, segments, out_path):
    lines = []
    
    # Title
    lines.append('# 佛教徒的人生态度')
    lines.append('# The Life Attitudes of Buddhists')
    lines.append('')
    lines.append('------2014年秋讲于第九届菩提静修营')
    lines.append('---Lecture Given at the 9th Bodhi Meditation Retreat, 2014')
    lines.append('')
    lines.append(' 济群法师 ')
    lines.append('Master Jiqun')
    lines.append('')
    
    # TOC from DOCX
    lines.append('- 一、消极还是积极')
    lines.append('- 二、悲观还是乐观')
    lines.append('- 三、禁欲还是纵欲')
    lines.append('- 四、重生还是重死')
    lines.append('- 五、自利还是利他')
    lines.append('- 六、出世还是入世')
    lines.append('- 七、无情还是多情')
    lines.append('- 八、随缘还是进取')
    lines.append('- 九、结束语')
    lines.append('')
    lines.append('- I. Passive or Proactive')
    lines.append('- II. Pessimism or Optimism')
    lines.append('- III. Abstinence or Indulgence')
    lines.append('- IV. Focus on Life or on Death')
    lines.append('- V. Benefit Oneself or Benefit Others')
    lines.append('- VI. Transcending the World or Engaging with the World')
    lines.append('- VII. To Love or Not to Love')
    lines.append('- VIII. Adapting to Conditions or Striving for Progress')
    lines.append('- IX. Conclusion')
    lines.append('')
    
    # Body
    for (cn, en), seg in zip(pairs, segments):
        target = seg if seg else en
        lines.append(cn)
        lines.append(target)
        lines.append('')
    
    with open(out_path, 'w') as f:
        f.write('\n'.join(lines))
    
    matched = sum(1 for s in segments if s is not None)
    print(f"Written: {out_path}")
    print(f"  Paragraphs: {len(pairs)}, matched from PDF: {matched}, fallback to DOCX: {len(pairs) - matched}")


if __name__ == '__main__':
    print("Extracting DOCX...")
    docx_text = pandoc(DOCX)
    pairs = extract_docx_pairs(docx_text)
    print(f"  Pairs: {len(pairs)}")
    
    print("Extracting PDF...")
    r = subprocess.run(['pdftotext', '-layout', PDF, '/tmp/_bilingual_pdf.txt'], check=True)
    with open('/tmp/_bilingual_pdf.txt') as f:
        pdf_raw = f.read()
    pdf_body = extract_pdf_body(pdf_raw)
    print(f"  PDF body: {len(pdf_body)} chars")
    
    print("Finding positions...")
    positions = find_positions(pairs, pdf_body)
    found = sum(1 for p in positions if p is not None)
    print(f"  Found: {found}/{len(pairs)}")
    
    print("Extracting segments...")
    segments = extract_segments(pdf_body, positions)
    
    out = os.path.join(OUT_DIR, 'bilingual.dj')
    generate(pairs, segments, out)
