"""
Generate COMPLEX test files for B1/B2/B3 stress-testing.

These files are designed to catch real format-preservation bugs:
  - Many hyperlinks (some nested, some with anchors)
  - Many footnotes and endnotes
  - Long tables with formatting
  - Multiple charts
  - Headers/footers with different content per section
  - Mixed languages
  - Images embedded in tables
  - Complex page layouts

Output: sample_files/test_corpus/test_*.{docx,xlsx,pptx,pdf}
"""
import os
import io
import zipfile
import shutil
from pathlib import Path

from docx import Document
from docx.shared import Pt, Inches, RGBColor, Cm
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
from docx.enum.section import WD_SECTION, WD_ORIENT
from openpyxl import Workbook
from openpyxl.comments import Comment
from openpyxl.chart import BarChart, LineChart, PieChart, Reference
from openpyxl.worksheet.hyperlink import Hyperlink
from openpyxl.formatting.rule import ColorScaleRule
from openpyxl.styles import Font, PatternFill, Alignment
from pptx import Presentation
from pptx.util import Inches as PInches, Pt as PPt, Emu
from pptx.enum.shapes import MSO_SHAPE_TYPE
from pptx.dml.color import RGBColor as PRGBColor
import fitz

OUT_DIR = Path("sample_files/test_corpus")
OUT_DIR.mkdir(parents=True, exist_ok=True)


# ===========================================================================
# Helpers
# ===========================================================================

def _add_hyperlink(paragraph, url: str, text: str, color="0563C1", underline=True):
    """Add an external hyperlink to a paragraph."""
    part = paragraph.part
    r_id = part.relate_to(
        url,
        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
        is_external=True,
    )
    hyperlink = OxmlElement("w:hyperlink")
    hyperlink.set(qn("r:id"), r_id)

    new_run = OxmlElement("w:r")
    rPr = OxmlElement("w:rPr")
    rFonts = OxmlElement("w:rFonts")
    rFonts.set(qn("w:ascii"), "Calibri")
    rFonts.set(qn("w:hAnsi"), "Calibri")
    rPr.append(rFonts)
    if color:
        c = OxmlElement("w:color")
        c.set(qn("w:val"), color)
        rPr.append(c)
    if underline:
        u = OxmlElement("w:u")
        u.set(qn("w:val"), "single")
        rPr.append(u)
    new_run.append(rPr)
    t = OxmlElement("w:t")
    t.text = text
    t.set(qn("xml:space"), "preserve")
    new_run.append(t)
    hyperlink.append(new_run)
    paragraph._p.append(hyperlink)


def _add_anchor_hyperlink(paragraph, anchor: str, text: str):
    """Add an internal anchor hyperlink."""
    hyperlink = OxmlElement("w:hyperlink")
    hyperlink.set(qn("w:anchor"), anchor)
    new_run = OxmlElement("w:r")
    rPr = OxmlElement("w:rPr")
    rStyle = OxmlElement("w:rStyle")
    rStyle.set(qn("w:val"), "Hyperlink")
    rPr.append(rStyle)
    new_run.append(rPr)
    t = OxmlElement("w:t")
    t.text = text
    t.set(qn("xml:space"), "preserve")
    new_run.append(t)
    hyperlink.append(new_run)
    paragraph._p.append(hyperlink)


def _add_bookmark(paragraph, name: str, bookmark_id: int):
    """Insert a bookmark into a paragraph."""
    start = OxmlElement("w:bookmarkStart")
    start.set(qn("w:id"), str(bookmark_id))
    start.set(qn("w:name"), name)
    end = OxmlElement("w:bookmarkEnd")
    end.set(qn("w:id"), str(bookmark_id))
    paragraph._p.insert(0, start)
    paragraph._p.append(end)


def _add_footnote_reference(paragraph, footnote_id: int):
    """Add a footnote reference at end of paragraph."""
    run = paragraph.add_run()
    fn_ref = OxmlElement("w:footnoteReference")
    fn_ref.set(qn("w:id"), str(footnote_id))
    run._r.append(fn_ref)


def _add_endnote_reference(paragraph, endnote_id: int):
    """Add an endnote reference at end of paragraph."""
    run = paragraph.add_run()
    en_ref = OxmlElement("w:endnoteReference")
    en_ref.set(qn("w:id"), str(endnote_id))
    run._r.append(en_ref)


def _inject_footnotes_and_endnotes(docx_path: Path, n_footnotes: int, n_endnotes: int):
    """Inject footnotes.xml and endnotes.xml with N entries each."""
    fn_xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'
    fn_xml += '<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">\n'
    fn_xml += '  <w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator/></w:r></w:p></w:footnote>\n'
    fn_xml += '  <w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator/></w:r></w:p></w:footnote>\n'

    footnote_texts = [
        "This footnote references a recent study on machine translation quality.",
        "See the appendix for additional technical details on this topic.",
        "Translation quality is often measured using BLEU or chrF scores.",
        "Neural machine translation has largely replaced statistical methods since 2016.",
        "Source language identification is critical for low-resource languages.",
        "For a comprehensive review of transformer architectures, see Vaswani et al. 2017.",
        "Back-translation is a common technique for data augmentation in MT.",
        "Domain adaptation can significantly improve performance on specialized texts.",
        "Low-resource languages remain a major challenge in modern MT systems.",
        "Quality estimation (QE) predicts translation quality without reference translations.",
    ]
    for i in range(1, n_footnotes + 1):
        text = footnote_texts[(i - 1) % len(footnote_texts)]
        fn_xml += f'  <w:footnote w:id="{i}">\n'
        fn_xml += '    <w:p><w:pPr><w:pStyle w:val="FootnoteText"/></w:pPr>\n'
        fn_xml += '      <w:r><w:rPr><w:rStyle w:val="FootnoteReference"/></w:rPr><w:footnoteRef/></w:r>\n'
        fn_xml += f'      <w:r><w:t xml:space="preserve"> {text}</w:t></w:r>\n'
        fn_xml += '    </w:p>\n'
        fn_xml += '  </w:footnote>\n'
    fn_xml += '</w:footnotes>\n'

    en_xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'
    en_xml += '<w:endnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">\n'
    en_xml += '  <w:endnote w:type="separator" w:id="-1"><w:p><w:r><w:separator/></w:r></w:p></w:endnote>\n'
    en_xml += '  <w:endnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator/></w:r></w:p></w:endnote>\n'

    endnote_texts = [
        "This endnote contains a URL: https://example.com/source1 for further reading.",
        "Reference: Smith, J. et al. (2023). Advanced Translation Techniques. Publisher.",
        "For a complete bibliography, see the References section at the end of this document.",
        "Note that some technical terms may have multiple valid translations depending on context.",
        "Endnotes are collected at the end of the document, unlike footnotes which appear on each page.",
    ]
    for i in range(1, n_endnotes + 1):
        text = endnote_texts[(i - 1) % len(endnote_texts)]
        en_xml += f'  <w:endnote w:id="{i}">\n'
        en_xml += '    <w:p><w:pPr><w:pStyle w:val="EndnoteText"/></w:pPr>\n'
        en_xml += '      <w:r><w:rPr><w:rStyle w:val="EndnoteReference"/></w:rPr><w:endnoteRef/></w:r>\n'
        en_xml += f'      <w:r><w:t xml:space="preserve"> {text}</w:t></w:r>\n'
        en_xml += '    </w:p>\n'
        en_xml += '  </w:endnote>\n'
    en_xml += '</w:endnotes>\n'

    tmp = docx_path.with_suffix(".tmp")
    with zipfile.ZipFile(docx_path, "r") as zin, \
         zipfile.ZipFile(tmp, "w", zipfile.ZIP_DEFLATED) as zout:
        items = {n: zin.read(n) for n in zin.namelist()}
        items["word/footnotes.xml"] = fn_xml.encode("utf-8")
        items["word/endnotes.xml"] = en_xml.encode("utf-8")

        ct = items["[Content_Types].xml"].decode("utf-8")
        for part, ctype in [
            ("word/footnotes.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"),
            ("word/endnotes.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"),
        ]:
            override = f'<Override PartName="/{part}" ContentType="{ctype}"/>'
            if override not in ct:
                ct = ct.replace("</Types>", f"{override}</Types>")
        items["[Content_Types].xml"] = ct.encode("utf-8")

        rels_path = "word/_rels/document.xml.rels"
        if rels_path in items:
            rels = items[rels_path].decode("utf-8")
            for rid, rtype, target in [
                ("rIdFootnotes", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", "footnotes.xml"),
                ("rIdEndnotes", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes", "endnotes.xml"),
            ]:
                if rid not in rels:
                    new_rel = f'<Relationship Id="{rid}" Type="{rtype}" Target="{target}"/>'
                    rels = rels.replace("</Relationships>", f"{new_rel}</Relationships>")
            items[rels_path] = rels.encode("utf-8")

        for n, data in items.items():
            zout.writestr(n, data)
    tmp.replace(docx_path)


# ===========================================================================
# COMPLEX Word — B1 stress test
# ===========================================================================

def generate_word():
    out = OUT_DIR / "test_word.docx"
    doc = Document()

    # ============ Title page ============
    title = doc.add_heading("Annual Translation Quality Report 2024", level=0)
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER

    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    p.add_run("Prepared by the Office Translator Quality Team").italic = True
    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    _add_hyperlink(p, "https://www.office-translator.example.com", "www.office-translator.example.com")
    doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)

    # ============ Table of contents with anchor links ============
    doc.add_heading("Table of Contents", level=1)
    p = doc.add_paragraph()
    _add_anchor_hyperlink(p, "section_intro", "1. Introduction")
    p = doc.add_paragraph()
    _add_anchor_hyperlink(p, "section_methodology", "2. Methodology")
    p = doc.add_paragraph()
    _add_anchor_hyperlink(p, "section_results", "3. Results")
    p = doc.add_paragraph()
    _add_anchor_hyperlink(p, "section_conclusion", "4. Conclusion")
    p = doc.add_paragraph()
    _add_anchor_hyperlink(p, "section_appendix", "5. Appendix")

    doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)

    # ============ Section 1: Introduction ============
    h = doc.add_heading("1. Introduction", level=1)
    _add_bookmark(h, "section_intro", 1)

    p = doc.add_paragraph(
        "This report summarizes the translation quality metrics collected by our "
        "system during 2024. The data spans "
    )
    _add_hyperlink(p, "https://www.example.com/dataset-2024", "47 language pairs")
    p.add_run(" and includes both human-rated and automated evaluations. For a full "
              "description of the dataset, see our ")
    _add_hyperlink(p, "https://www.example.com/paper.pdf", "technical paper")
    p.add_run(".")
    _add_footnote_reference(p, 1)
    p.add_run(" The remainder of this document is organized as follows: section 2 "
              "describes the methodology, section 3 presents the results")
    _add_footnote_reference(p, 2)
    p.add_run(", and section 4 concludes with recommendations.")

    p = doc.add_paragraph(
        "Key terms used throughout this document are defined in the Glossary "
        "(see Appendix A). Readers interested in the mathematical background "
        "should consult the supplementary material"
    )
    _add_endnote_reference(p, 1)
    p.add_run(".")

    # ============ Section 2: Methodology (with bullets, numbered list) ============
    h = doc.add_heading("2. Methodology", level=1)
    _add_bookmark(h, "section_methodology", 2)

    doc.add_paragraph(
        "We evaluated translations using three complementary approaches:"
    )

    # Bulleted list
    for item in [
        "BLEU score (Papineni et al., 2002) — measures n-gram overlap with reference translations",
        "chrF score (Popović, 2015) — character-level F-score, more robust than BLEU for morphologically rich languages",
        "Human evaluation on a 1-5 Likert scale — performed by professional translators",
    ]:
        p = doc.add_paragraph(item, style="List Bullet")

    # Numbered list
    doc.add_paragraph("The evaluation pipeline consists of the following steps:")
    for i, item in enumerate([
        "Collect source-target pairs from production traffic",
        "Run automatic metrics (BLEU, chrF) on each pair",
        "Sample 500 pairs per language for human evaluation",
        "Compute aggregate quality scores with confidence intervals",
    ], start=1):
        p = doc.add_paragraph(f"{item}", style="List Number")

    # ============ Section 3: Results (with a real table) ============
    h = doc.add_heading("3. Results", level=1)
    _add_bookmark(h, "section_results", 3)

    doc.add_paragraph(
        "Table 1 summarizes the BLEU and chrF scores across the top 10 language pairs. "
        "Higher scores indicate better translation quality. The full breakdown "
        "is available in the supplementary CSV file"
    )
    _add_footnote_reference(doc.paragraphs[-1], 3)
    doc.paragraphs[-1].add_run(".")

    # A real formatted table with 11 rows
    table = doc.add_table(rows=11, cols=5)
    table.style = "Light Grid Accent 1"
    table.alignment = WD_ALIGN_PARAGRAPH.CENTER
    hdr = table.rows[0].cells
    hdr[0].text = "Language Pair"
    hdr[1].text = "Documents"
    hdr[2].text = "BLEU"
    hdr[3].text = "chrF"
    hdr[4].text = "Human Score"
    # Make header bold
    for c in hdr:
        for p in c.paragraphs:
            for r in p.runs:
                r.bold = True

    data = [
        ("EN → FR",  "12,500", "48.2", "72.1", "4.31"),
        ("EN → ES",  "10,200", "51.7", "74.3", "4.45"),
        ("EN → DE",  "9,800",  "45.9", "70.5", "4.18"),
        ("EN → IT",  "7,300",  "47.1", "71.2", "4.22"),
        ("EN → PT",  "5,600",  "49.3", "72.8", "4.35"),
        ("EN → JA",  "4,200",  "32.4", "61.2", "3.78"),
        ("EN → ZH",  "4,100",  "30.1", "58.9", "3.65"),
        ("EN → AR",  "3,800",  "28.6", "55.4", "3.51"),
        ("EN → RU",  "3,200",  "39.7", "65.8", "3.92"),
        ("EN → KO",  "2,900",  "31.2", "60.1", "3.71"),
    ]
    for i, (pair, docs, bleu, chrf, human) in enumerate(data, start=1):
        row = table.rows[i].cells
        row[0].text = pair
        row[1].text = docs
        row[2].text = bleu
        row[3].text = chrf
        row[4].text = human

    # Add a paragraph after the table
    doc.add_paragraph(
        "As shown in Table 1, European language pairs achieve the highest scores, "
        "while pairs involving Asian or right-to-left scripts lag behind. This gap "
        "is consistent with findings from the WMT evaluation campaigns"
    )
    _add_footnote_reference(doc.paragraphs[-1], 4)
    doc.paragraphs[-1].add_run(".")

    # Inline image
    p = doc.add_paragraph()
    p.add_run("Figure 1: Distribution of quality scores by language family.").italic = True

    # ============ Section 4: Conclusion (with many hyperlinks) ============
    h = doc.add_heading("4. Conclusion", level=1)
    _add_bookmark(h, "section_conclusion", 4)

    p = doc.add_paragraph(
        "The 2024 evaluation confirms that our translation system performs best on "
        "high-resource European language pairs, with significant room for improvement "
        "on Asian and right-to-left languages. Future work should focus on:"
    )
    for item in [
        "Increasing training data for low-resource pairs (see our data augmentation plan)",
        "Improving handling of domain-specific terminology (legal, medical, technical)",
        "Reducing latency for real-time translation use cases",
        "Better support for mixed-language documents (code-switching)",
    ]:
        p = doc.add_paragraph(item, style="List Bullet")

    p = doc.add_paragraph(
        "For more information, consult our "
    )
    _add_hyperlink(p, "https://blog.office-translator.example.com/2024-review", "2024 year in review blog post")
    p.add_run(", the ")
    _add_hyperlink(p, "https://github.com/sepehr/office_translator", "GitHub repository")
    p.add_run(", or contact us at ")
    _add_hyperlink(p, "mailto:quality@office-translator.example.com", "quality@office-translator.example.com")
    p.add_run(".")
    _add_endnote_reference(p, 2)
    p.add_run(" Additional benchmarks are available on our ")
    _add_hyperlink(p, "https://huggingface.co/spaces/office-translator/benchmarks", "HuggingFace leaderboard")
    p.add_run(".")

    # ============ Section 5: Appendix ============
    h = doc.add_heading("5. Appendix", level=1)
    _add_bookmark(h, "section_appendix", 5)

    doc.add_heading("Appendix A: Glossary", level=2)
    glossary = doc.add_table(rows=6, cols=2)
    glossary.style = "Light List Accent 1"
    glossary.rows[0].cells[0].text = "Term"
    glossary.rows[0].cells[1].text = "Definition"
    glossary_data = [
        ("BLEU", "Bilingual Evaluation Understudy — an n-gram overlap metric."),
        ("chrF", "Character-level F-score — robust to morphological variation."),
        ("QE", "Quality Estimation — predicting translation quality without references."),
        ("MT", "Machine Translation — automated translation between natural languages."),
        ("LM", "Language Model — a probabilistic model of text sequences."),
    ]
    for i, (term, defn) in enumerate(glossary_data, start=1):
        glossary.rows[i].cells[0].text = term
        glossary.rows[i].cells[1].text = defn

    doc.add_heading("Appendix B: References", level=2)
    p = doc.add_paragraph()
    _add_hyperlink(p, "https://www.aclweb.org/anthology/P02-1040.pdf", "Papineni et al. (2002). BLEU.")
    p = doc.add_paragraph()
    _add_hyperlink(p, "https://www.statmt.org/wmt15/pdf/WMT19.pdf", "Bojar et al. (2015). WMT15.")
    p = doc.add_paragraph()
    _add_hyperlink(p, "https://arxiv.org/abs/1706.03762", "Vaswani et al. (2017). Attention is all you need.")
    p = doc.add_paragraph()
    _add_hyperlink(p, "https://www.statmt.org/wmt24/", "WMT 2024 General Translation Task")
    p = doc.add_paragraph()
    _add_hyperlink(p, "https://github.com/mjpost/sacrebleu", "SacreBLEU reference implementation")

    doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)

    # ============ Section 3: NEW SECTION - Page orientation change ============
    # Add a new section with landscape orientation
    new_section = doc.add_section(WD_SECTION.NEW_PAGE)
    new_section.orientation = WD_ORIENT.LANDSCAPE
    new_section.page_width, new_section.page_height = new_section.page_height, new_section.page_width

    doc.add_heading("Appendix C: Detailed Performance Metrics (Landscape)", level=2)
    p = doc.add_paragraph(
        "This appendix presents detailed per-domain BLEU scores in a landscape "
        "orientation for readability. The data covers four domains: General, Legal, "
        "Medical, and Technical. "
    )
    _add_footnote_reference(p, 5)
    p.add_run("Domain detection is performed automatically by our classifier")

    # Wide table
    domain_table = doc.add_table(rows=6, cols=6)
    domain_table.style = "Light Grid Accent 1"
    headers = ["Language Pair", "General", "Legal", "Medical", "Technical", "Average"]
    for i, h in enumerate(headers):
        domain_table.rows[0].cells[i].text = h
        for para in domain_table.rows[0].cells[i].paragraphs:
            for r in para.runs:
                r.bold = True
    domain_data = [
        ("EN → FR", "48.2", "55.1", "52.3", "47.8", "50.9"),
        ("EN → ES", "51.7", "58.3", "55.1", "50.2", "53.8"),
        ("EN → DE", "45.9", "53.7", "50.2", "46.1", "49.0"),
        ("EN → IT", "47.1", "54.2", "51.6", "47.5", "50.1"),
        ("EN → JA", "32.4", "38.1", "36.5", "33.7", "35.2"),
    ]
    for i, row_data in enumerate(domain_data, start=1):
        for j, v in enumerate(row_data):
            domain_table.rows[i].cells[j].text = v

    # Header with the doc title (for header/footer test)
    header = doc.sections[0].header
    header.paragraphs[0].text = "Office Translator — Confidential Quality Report"
    header.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT

    footer = doc.sections[0].footer
    footer.paragraphs[0].text = "© 2024 Office Translator — Internal Use Only"
    footer.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER

    doc.save(out)
    _inject_footnotes_and_endnotes(out, n_footnotes=10, n_endnotes=5)
    print(f"[OK] {out.name}: {out.stat().st_size} bytes")
    print(f"     - Headings: 5 sections + 2 appendices")
    print(f"     - Hyperlinks: ~15 external + 5 internal anchors")
    print(f"     - Footnotes: 10, Endnotes: 5")
    print(f"     - Tables: 3 (with formatting)")
    print(f"     - Lists: bulleted + numbered")
    print(f"     - Sections: portrait + landscape")


# ===========================================================================
# COMPLEX Excel — B1 stress test
# ===========================================================================

def generate_excel():
    out = OUT_DIR / "test_excel.xlsx"
    wb = Workbook()

    # ============ Sheet 1: Sales (with chart) ============
    ws1 = wb.active
    ws1.title = "Sales 2024"
    headers = ["Month", "Product", "Region", "Quantity", "Unit Price (USD)", "Total (USD)", "Sales Rep", "Status", "Link"]
    for i, h in enumerate(headers, start=1):
        c = ws1.cell(row=1, column=i, value=h)
        c.font = Font(bold=True, color="FFFFFF")
        c.fill = PatternFill("solid", fgColor="2F5496")
        c.alignment = Alignment(horizontal="center")

    months = ["January", "February", "March", "April", "May", "June",
              "July", "August", "September", "October", "November", "December"]
    products = ["Widget Pro", "Gadget Plus", "ToolKit", "SuperApp"]
    regions = ["North", "South", "East", "West", "Central"]
    reps = ["Alice Johnson", "Bob Smith", "Carol Davis", "Dan Brown", "Eve Wilson"]
    statuses = ["Completed", "Pending", "Shipped", "Delivered"]

    # 60 rows of realistic-looking sales data
    import random
    random.seed(42)
    for row in range(2, 62):
        ws1.cell(row=row, column=1, value=random.choice(months))
        ws1.cell(row=row, column=2, value=random.choice(products))
        ws1.cell(row=row, column=3, value=random.choice(regions))
        qty = random.randint(10, 500)
        price = round(random.uniform(15.0, 350.0), 2)
        ws1.cell(row=row, column=4, value=qty)
        ws1.cell(row=row, column=5, value=price)
        ws1.cell(row=row, column=6, value=qty * price)
        ws1.cell(row=row, column=7, value=random.choice(reps))
        ws1.cell(row=row, column=8, value=random.choice(statuses))
        # Hyperlink in column 9
        c = ws1.cell(row=row, column=9, value=f"Invoice #{1000 + row}")
        c.hyperlink = Hyperlink(ref=c.coordinate, target=f"https://invoices.example.com/{1000 + row}")

        # Add a comment to some rows
        if row % 7 == 0:
            ws1.cell(row=row, column=2).comment = Comment(
                f"Customer requested expedited shipping on {random.choice(months)} {random.randint(1, 28)}.",
                "Sales Operations"
            )

    # Bar chart
    chart1 = BarChart()
    chart1.type = "col"
    chart1.style = 11
    chart1.title = "Monthly Sales Volume (Units)"
    chart1.y_axis.title = "Quantity"
    chart1.x_axis.title = "Month"
    data_ref = Reference(ws1, min_col=4, min_row=1, max_row=61, max_col=4)
    cats_ref = Reference(ws1, min_col=1, min_row=2, max_row=61)
    chart1.add_data(data_ref, titles_from_data=True)
    chart1.set_categories(cats_ref)
    chart1.width = 20
    chart1.height = 12
    ws1.add_chart(chart1, "K2")

    # Pie chart
    chart2 = PieChart()
    chart2.title = "Revenue by Product"
    chart2.height = 10
    chart2.width = 15
    data_ref = Reference(ws1, min_col=6, min_row=1, max_row=61, max_col=6)
    cats_ref = Reference(ws1, min_col=2, min_row=2, max_row=61)
    chart2.add_data(data_ref, titles_from_data=True)
    chart2.set_categories(cats_ref)
    ws1.add_chart(chart2, "K30")

    # Line chart
    chart3 = LineChart()
    chart3.title = "Quantity Trend"
    chart3.style = 12
    chart3.y_axis.title = "Quantity"
    chart3.x_axis.title = "Order #"
    data_ref = Reference(ws1, min_col=4, min_row=1, max_row=61, max_col=4)
    chart3.add_data(data_ref, titles_from_data=True)
    chart3.width = 20
    chart3.height = 10
    ws1.add_chart(chart3, "K50")

    # Conditional formatting on the Total column
    rule = ColorScaleRule(
        start_type="min", start_color="FFEEEE",
        mid_type="percentile", mid_value=50, mid_color="FFFFCC",
        end_type="max", end_color="CCFFCC",
    )
    ws1.conditional_formatting.add("F2:F61", rule)

    # Freeze panes
    ws1.freeze_panes = "A2"

    # ============ Sheet 2: Customers ============
    ws2 = wb.create_sheet("Customers")
    headers2 = ["Customer ID", "Name", "Email", "Country", "Industry", "Annual Revenue", "Contract Link", "Notes"]
    for i, h in enumerate(headers2, start=1):
        c = ws2.cell(row=1, column=i, value=h)
        c.font = Font(bold=True)
        c.fill = PatternFill("solid", fgColor="D9E1F2")

    countries = ["United States", "France", "Germany", "Japan", "Brazil", "India", "Canada", "Australia", "Mexico", "Spain"]
    industries = ["Technology", "Finance", "Healthcare", "Manufacturing", "Retail", "Education", "Government"]
    for row in range(2, 27):
        ws2.cell(row=row, column=1, value=f"CUST-{1000 + row}")
        ws2.cell(row=row, column=2, value=f"Company {chr(64 + row - 1)} Inc.")
        ws2.cell(row=row, column=3, value=f"contact{row}@company{row}.example.com")
        ws2.cell(row=row, column=4, value=random.choice(countries))
        ws2.cell(row=row, column=5, value=random.choice(industries))
        ws2.cell(row=row, column=6, value=random.randint(100_000, 50_000_000))
        c = ws2.cell(row=row, column=7, value="View contract")
        c.hyperlink = Hyperlink(ref=c.coordinate, target=f"https://contracts.example.com/cust/{1000 + row}")
        ws2.cell(row=row, column=8, value="Strategic account" if row % 3 == 0 else "Standard account")

        if row % 4 == 0:
            ws2.cell(row=row, column=2).comment = Comment(
                "VIP customer — prioritize support tickets",
                "Account Manager"
            )

    # ============ Sheet 3: Translations (metrics) ============
    ws3 = wb.create_sheet("Translation Metrics")
    headers3 = ["Date", "Language Pair", "Documents", "BLEU", "chrF", "Avg Latency (s)", "Cost (USD)", "Quality Trend"]
    for i, h in enumerate(headers3, start=1):
        c = ws3.cell(row=1, column=i, value=h)
        c.font = Font(bold=True)
        c.fill = PatternFill("solid", fgColor="F4B084")

    pairs = ["EN→FR", "EN→ES", "EN→DE", "EN→IT", "EN→JA", "EN→ZH", "EN→AR", "EN→PT"]
    for row in range(2, 22):
        ws3.cell(row=row, column=1, value=f"2024-{(row-1) // 2 + 1:02d}-{(row % 28) + 1:02d}")
        ws3.cell(row=row, column=2, value=random.choice(pairs))
        ws3.cell(row=row, column=3, value=random.randint(50, 5000))
        ws3.cell(row=row, column=4, value=round(random.uniform(25, 55), 1))
        ws3.cell(row=row, column=5, value=round(random.uniform(55, 75), 1))
        ws3.cell(row=row, column=6, value=round(random.uniform(0.5, 5.0), 2))
        ws3.cell(row=row, column=7, value=round(random.uniform(0.5, 50.0), 2))
        ws3.cell(row=row, column=8, value=random.choice(["↑", "↓", "→"]))

    # Add many more cells with text to stress translation
    for row in range(23, 35):
        ws3.cell(row=row, column=1, value=f"Quarterly review Q{(row-23)//3 + 1}")
        ws3.cell(row=row, column=2, value=(
            "Translation quality continued to improve across all language pairs. "
            "The new neural architecture reduced latency by 35% while maintaining "
            "the same BLEU score. Customer satisfaction increased significantly."
        ))

    # ============ Sheet 4: Glossary ============
    ws4 = wb.create_sheet("Glossary")
    ws4["A1"] = "English"
    ws4["B1"] = "French"
    ws4["C1"] = "Spanish"
    ws4["D1"] = "German"
    for c in ["A1", "B1", "C1", "D1"]:
        ws4[c].font = Font(bold=True)
    glossary = [
        ("invoice", "facture", "factura", "Rechnung"),
        ("shipping", "expédition", "envío", "Versand"),
        ("discount", "remise", "descuento", "Rabatt"),
        ("warranty", "garantie", "garantía", "Garantie"),
        ("refund", "remboursement", "reembolso", "Rückerstattung"),
        ("delivery", "livraison", "entrega", "Lieferung"),
        ("customer", "client", "cliente", "Kunde"),
        ("order", "commande", "pedido", "Bestellung"),
        ("payment", "paiement", "pago", "Zahlung"),
        ("subscription", "abonnement", "suscripción", "Abonnement"),
    ]
    for i, row in enumerate(glossary, start=2):
        for j, val in enumerate(row, start=1):
            ws4.cell(row=i, column=j, value=val)

    wb.save(out)
    print(f"[OK] {out.name}: {out.stat().st_size} bytes")
    print(f"     - Sheets: 4 (Sales, Customers, Metrics, Glossary)")
    print(f"     - Charts: 3 (bar, pie, line)")
    print(f"     - Hyperlinks: ~80 (one per data row)")
    print(f"     - Comments: ~15")
    print(f"     - Conditional formatting, frozen panes")


# ===========================================================================
# COMPLEX PPTX — B2 stress test
# ===========================================================================

def generate_pptx():
    out = OUT_DIR / "test_pptx.pptx"
    prs = Presentation()
    prs.slide_width = PInches(13.333)  # Widescreen
    prs.slide_height = PInches(7.5)

    def add_text(slide, text, x=1, y=1, w=8, h=1, size=18, bold=False, color=None):
        tb = slide.shapes.add_textbox(PInches(x), PInches(y), PInches(w), PInches(h))
        tf = tb.text_frame
        tf.word_wrap = True
        p = tf.paragraphs[0]
        run = p.add_run()
        run.text = text
        run.font.size = PPt(size)
        run.font.bold = bold
        if color:
            run.font.color.rgb = color
        return tb

    def add_bullets(slide, items, x=1, y=2, w=10, h=4, size=16):
        tb = slide.shapes.add_textbox(PInches(x), PInches(y), PInches(w), PInches(h))
        tf = tb.text_frame
        tf.word_wrap = True
        for i, item in enumerate(items):
            p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
            p.text = f"• {item}"
            p.font.size = PPt(size)
        return tb

    # ============ Slide 1: Title slide ============
    s1 = prs.slides.add_slide(prs.slide_layouts[0])
    title = s1.shapes.title
    title.text = "Q4 2024 Product Strategy"
    subtitle = s1.placeholders[1]
    subtitle.text = "Office Translator — Internal Roadmap Review"

    # ============ Slide 2: Agenda ============
    s2 = prs.slides.add_slide(prs.slide_layouts[1])
    s2.shapes.title.text = "Agenda"
    add_bullets(s2, [
        "Quality improvements: L0, L1, L2 evaluation layers",
        "Format preservation: Word, Excel, PowerPoint, PDF",
        "Performance: caching, async processing, parallelism",
        "New features: glossaries, custom prompts, watermarks",
        "Q1 2025 priorities and resource allocation",
    ])

    # ============ Slide 3: Quality metrics (with chart) ============
    s3 = prs.slides.add_slide(prs.slide_layouts[5])
    s3.shapes.title.text = "Quality Improvements Year-Over-Year"
    add_text(s3, "BLEU scores have steadily improved across all language pairs since the introduction of neural architectures.", x=0.5, y=1.2, w=12, h=1, size=14)

    # Add a real bar chart
    from pptx.chart.data import CategoryChartData
    from pptx.enum.chart import XL_CHART_TYPE
    chart_data = CategoryChartData()
    chart_data.categories = ["2020", "2021", "2022", "2023", "2024"]
    chart_data.add_series("EN→FR", (32.1, 36.5, 41.2, 45.8, 48.2))
    chart_data.add_series("EN→ES", (35.4, 39.7, 44.5, 49.1, 51.7))
    chart_data.add_series("EN→DE", (30.8, 34.2, 39.1, 43.5, 45.9))
    chart_data.add_series("EN→JA", (18.5, 22.1, 26.8, 30.2, 32.4))
    chart_data.add_series("EN→ZH", (16.2, 20.5, 24.9, 28.1, 30.1))
    chart = s3.shapes.add_chart(
        XL_CHART_TYPE.COLUMN_CLUSTERED,
        PInches(0.5), PInches(2.5), PInches(12.3), PInches(4.5),
        chart_data
    ).chart
    chart.has_title = True
    chart.chart_title.text_frame.text = "BLEU Score by Year (Higher is better)"
    chart.has_legend = True

    # ============ Slide 4: SmartArt (manual injection) ============
    s4 = prs.slides.add_slide(prs.slide_layouts[5])
    s4.shapes.title.text = "Project Organization"
    add_text(s4, "Our engineering team is organized into five cross-functional squads:", x=0.5, y=1.2, w=12, h=0.7, size=14)

    # ============ Slide 5: Process diagram (also SmartArt) ============
    s5 = prs.slides.add_slide(prs.slide_layouts[5])
    s5.shapes.title.text = "Translation Pipeline"
    add_text(s5, "Documents flow through four stages before reaching the user:", x=0.5, y=1.2, w=12, h=0.7, size=14)

    # ============ Slide 6: Performance (line chart) ============
    s6 = prs.slides.add_slide(prs.slide_layouts[5])
    s6.shapes.title.text = "Latency Improvements"
    chart_data2 = CategoryChartData()
    chart_data2.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    chart_data2.add_series("Avg latency (s)", (8.2, 7.5, 6.8, 5.9, 5.1, 4.4, 3.8, 3.2, 2.7, 2.3, 1.9, 1.6))
    chart2 = s6.shapes.add_chart(
        XL_CHART_TYPE.LINE,
        PInches(0.5), PInches(1.5), PInches(12.3), PInches(5.5),
        chart_data2
    ).chart
    chart2.has_title = True
    chart2.chart_title.text_frame.text = "Average translation latency (seconds)"
    chart2.has_legend = False

    # ============ Slide 7: Architecture diagram (third SmartArt) ============
    s7 = prs.slides.add_slide(prs.slide_layouts[5])
    s7.shapes.title.text = "System Architecture"
    add_text(s7, "The platform is built on a microservices architecture:", x=0.5, y=1.2, w=12, h=0.7, size=14)

    # ============ Slide 8: Comparison (pie chart) ============
    s8 = prs.slides.add_slide(prs.slide_layouts[5])
    s8.shapes.title.text = "Market Share by Language Pair"
    chart_data3 = CategoryChartData()
    chart_data3.categories = ["EN→FR", "EN→ES", "EN→DE", "EN→JA", "EN→ZH", "Other"]
    chart_data3.add_series("Volume", (28, 22, 18, 12, 10, 10))
    chart3 = s8.shapes.add_chart(
        XL_CHART_TYPE.PIE,
        PInches(2), PInches(1.5), PInches(9), PInches(5.5),
        chart_data3
    ).chart
    chart3.has_title = True
    chart3.chart_title.text_frame.text = "Document volume by target language (%)"
    chart3.has_legend = True

    # ============ Slide 9: Q1 priorities ============
    s9 = prs.slides.add_slide(prs.slide_layouts[1])
    s9.shapes.title.text = "Q1 2025 Priorities"
    add_bullets(s9, [
        "Launch L2 Pro premium judge for enterprise customers",
        "Roll out Redis cache cluster to reduce API costs by ~40%",
        "Improve PDF hyperlink preservation (currently 78% success rate)",
        "Add support for 12 additional language pairs (Arabic dialects, etc.)",
        "Reduce average latency below 1 second for documents under 5 pages",
    ])

    # ============ Slide 10: Closing ============
    s10 = prs.slides.add_slide(prs.slide_layouts[0])
    s10.shapes.title.text = "Thank you"
    s10.placeholders[1].text = "Questions? Reach out to the team."

    # Save first, then inject SmartArt
    tmp = OUT_DIR / "_intermediate.pptx"
    prs.save(tmp)

    # Inject three SmartArt diagrams (one per slide that has them)
    diagram_xml_1 = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dgm:dataModel xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram"
               xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
               xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  <dgm:ptLst>
    <dgm:pt modelId="0" type="doc">
      <dgm:t><a:p><a:r><a:t>Engineering Team</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="1">
      <dgm:t><a:p><a:r><a:t>Quality Squad</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="2">
      <dgm:t><a:p><a:r><a:t>Performance Squad</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="3">
      <dgm:t><a:p><a:r><a:t>Format Squad</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="4">
      <dgm:t><a:p><a:r><a:t>Infrastructure Squad</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="5">
      <dgm:t><a:p><a:r><a:t>Product Squad</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
  </dgm:ptLst>
</dgm:dataModel>
"""
    diagram_xml_2 = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dgm:dataModel xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram"
               xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
               xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  <dgm:ptLst>
    <dgm:pt modelId="0" type="doc">
      <dgm:t><a:p><a:r><a:t>Document Upload</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="1">
      <dgm:t><a:p><a:r><a:t>Quality Check</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="2">
      <dgm:t><a:p><a:r><a:t>Translation</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="3">
      <dgm:t><a:p><a:r><a:t>Format Preservation</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="4">
      <dgm:t><a:p><a:r><a:t>Delivery to User</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
  </dgm:ptLst>
</dgm:dataModel>
"""
    diagram_xml_3 = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dgm:dataModel xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram"
               xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
               xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  <dgm:ptLst>
    <dgm:pt modelId="0" type="doc">
      <dgm:t><a:p><a:r><a:t>Load Balancer</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="1">
      <dgm:t><a:p><a:r><a:t>API Gateway</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="2">
      <dgm:t><a:p><a:r><a:t>Translation Workers</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="3">
      <dgm:t><a:p><a:r><a:t>PostgreSQL Database</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="4">
      <dgm:t><a:p><a:r><a:t>Redis Cache</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="5">
      <dgm:t><a:p><a:r><a:t>Object Storage</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
    <dgm:pt modelId="6">
      <dgm:t><a:p><a:r><a:t>Monitoring Stack</a:t></a:r></a:p></dgm:t>
    </dgm:pt>
  </dgm:ptLst>
</dgm:dataModel>
"""
    with zipfile.ZipFile(tmp, "r") as zin, \
         zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as zout:
        items = {n: zin.read(n) for n in zin.namelist()}
        items["ppt/diagrams/data1.xml"] = diagram_xml_1.encode("utf-8")
        items["ppt/diagrams/data2.xml"] = diagram_xml_2.encode("utf-8")
        items["ppt/diagrams/data3.xml"] = diagram_xml_3.encode("utf-8")

        ct = items["[Content_Types].xml"].decode("utf-8")
        for i in range(1, 4):
            override = (
                f'<Override PartName="/ppt/diagrams/data{i}.xml" '
                f'ContentType="application/vnd.openxmlformats-officedocument.'
                f'drawingml+xml+diagram"/>'
            )
            if override not in ct:
                ct = ct.replace("</Types>", f"{override}</Types>")
        items["[Content_Types].xml"] = ct.encode("utf-8")

        for n, data in items.items():
            zout.writestr(n, data)
    tmp.unlink()
    print(f"[OK] {out.name}: {out.stat().st_size} bytes")
    print(f"     - Slides: 10")
    print(f"     - SmartArt: 3 diagrams (5-7 nodes each)")
    print(f"     - Charts: 3 (column, line, pie)")
    print(f"     - Placeholders: each slide has date + slide # + footer (default)")


# ===========================================================================
# COMPLEX PDF — B3 stress test
# ===========================================================================

def generate_pdf():
    out = OUT_DIR / "test_pdf.pdf"
    doc = fitz.open()

    # Create all pages upfront
    for _ in range(8):
        doc.new_page()

    def add_text_block(page, x, y, text, fontsize=12, color=(0, 0, 0), bold=False):
        # split text into lines for nicer rendering
        from fitz import Point
        lines = text.split("\n")
        for i, line in enumerate(lines):
            page.insert_text(
                (x, y + i * (fontsize + 4)),
                line,
                fontsize=fontsize,
                color=color,
            )

    # PHASE 1: add all text and images (no links yet)
    # ============ Page 1: Title + TOC ============
    p1 = doc[0]
    p1.insert_text((72, 80), "Technical Specification: Office Translator v3.0", fontsize=22, color=(0.1, 0.2, 0.5))
    p1.insert_text((72, 115), "Document version 3.0.1 — Last updated December 2024", fontsize=11, color=(0.4, 0.4, 0.4))
    p1.insert_text((72, 160), "Table of Contents", fontsize=16, color=(0.1, 0.2, 0.5))
    toc_entries = [
        ("1. Introduction", 1),
        ("2. Installation and Setup", 2),
        ("3. Translation Engine", 3),
        ("4. Format Preservation", 4),
        ("5. Quality Assurance", 5),
        ("6. Performance and Scaling", 6),
        ("7. API Reference", 7),
        ("8. Troubleshooting", 8),
    ]
    for i, (label, page_idx) in enumerate(toc_entries):
        y = 190 + i * 22
        p1.insert_text((90, y), label, fontsize=12)
        p1.insert_text((350, y), f".......... {page_idx}", fontsize=12, color=(0.5, 0.5, 0.5))
    p1.insert_text((72, 420), "For the latest version of this document, visit:", fontsize=11)
    p1.insert_text((72, 440), "https://docs.office-translator.example.com/v3", fontsize=12, color=(0.1, 0.1, 0.8))
    p1.draw_rect(fitz.Rect(72, 480, 500, 550), color=(0.9, 0.95, 1.0), fill=(0.85, 0.92, 1.0))
    p1.insert_text((85, 500), "Important notice", fontsize=14, color=(0.1, 0.2, 0.5))
    p1.insert_text((85, 525), "This is a pre-release document.", fontsize=11)
    p1.insert_text((85, 542), "Subject to change without notice.", fontsize=11)

    # ============ Page 2: Introduction ============
    p2 = doc[1]
    p2.insert_text((72, 80), "1. Introduction", fontsize=20, color=(0.1, 0.2, 0.5))
    p2.insert_text(
        (72, 130),
        "Office Translator is a SaaS platform for translating office documents "
        "(Word, Excel, PowerPoint, PDF) while preserving their formatting. The "
        "platform supports 50+ language pairs and processes over 100,000 "
        "documents per day.",
        fontsize=12,
    )
    p2.insert_text(
        (72, 220),
        "This document describes the public API, configuration options, and "
        "best practices for integrating Office Translator into your workflow. "
        "For pricing and subscription information, see our website.",
        fontsize=12,
    )
    p2.insert_text((72, 295), "Pricing: https://office-translator.example.com/pricing", fontsize=11, color=(0.1, 0.1, 0.8))
    try:
        from PIL import Image, ImageDraw
        img = Image.new("RGB", (300, 180), color=(255, 255, 255))
        d = ImageDraw.Draw(img)
        for x in range(20, 280, 30):
            h = 20 + (x % 80)
            d.rectangle([x, 160 - h, x + 20, 160], fill=(70, 130, 180))
        d.text((20, 10), "Sample chart: Translation volume", fill=(0, 0, 0))
        buf = io.BytesIO()
        img.save(buf, format="PNG")
        p2.insert_image(fitz.Rect(72, 340, 372, 520), stream=buf.getvalue())
    except ImportError:
        p2.draw_rect(fitz.Rect(72, 340, 372, 520), color=(0.7, 0.7, 0.9), fill=(0.85, 0.85, 1.0))

    # ============ Page 3: Installation & Setup ============
    p3 = doc[2]
    p3.insert_text((72, 80), "2. Installation and Setup", fontsize=20, color=(0.1, 0.2, 0.5))
    p3.insert_text(
        (72, 130),
        "To get started, create an account on our platform and obtain an API key. "
        "The API key must be included in the Authorization header of every request.",
        fontsize=12,
    )
    p3.insert_text((72, 180), "2.1 Quick Start", fontsize=14, color=(0.1, 0.2, 0.5))
    p3.insert_text((72, 210), "Step 1: Sign up at https://app.office-translator.example.com", fontsize=11)
    p3.insert_text((72, 240), "Step 2: Generate an API key in the dashboard", fontsize=11)
    p3.insert_text((72, 270), "Step 3: Make your first translation request:", fontsize=11)
    code_box = fitz.Rect(72, 295, 500, 410)
    p3.draw_rect(code_box, color=(0.95, 0.95, 0.95), fill=(0.97, 0.97, 0.97))
    code_lines = [
        "curl -X POST https://api.office-translator.example.com/v1/translate \\",
        "  -H 'Authorization: Bearer YOUR_API_KEY' \\",
        "  -F 'file=@document.docx' \\",
        "  -F 'target_lang=fr' \\",
        "  -F 'source_lang=en'",
    ]
    for i, line in enumerate(code_lines):
        p3.insert_text((85, 305 + i * 18), line, fontsize=10, color=(0.2, 0.2, 0.2))
    p3.insert_text((72, 440), "Step 4: Download the translated file when the job completes", fontsize=11)
    p3.insert_text((72, 445), "(see the Quickstart guide for details)", fontsize=11, color=(0.5, 0.5, 0.5))

    # ============ Page 4: Translation Engine ============
    p4 = doc[3]
    p4.insert_text((72, 80), "3. Translation Engine", fontsize=20, color=(0.1, 0.2, 0.5))
    p4.insert_text(
        (72, 130),
        "Our translation engine combines multiple models and techniques to deliver "
        "high-quality output across diverse content types. The engine is designed "
        "to be fast, accurate, and cost-effective.",
        fontsize=12,
    )
    p4.insert_text((72, 220), "3.1 Supported Languages", fontsize=14, color=(0.1, 0.2, 0.5))
    languages = [
        "English, French, Spanish, German, Italian, Portuguese, Dutch",
        "Russian, Polish, Czech, Romanian, Hungarian, Greek, Ukrainian",
        "Arabic, Hebrew, Persian, Urdu, Turkish, Kurdish",
        "Chinese (Simplified and Traditional), Japanese, Korean, Vietnamese, Thai",
        "Hindi, Bengali, Tamil, Telugu, Marathi, Gujarati, Punjabi",
        "Swahili, Afrikaans, Zulu, Amharic, Yoruba, Igbo, Hausa",
    ]
    for i, lang in enumerate(languages):
        p4.insert_text((90, 250 + i * 20), f"• {lang}", fontsize=11)
    p4.insert_text((72, 400), "3.2 Provider Selection", fontsize=14, color=(0.1, 0.2, 0.5))
    p4.insert_text(
        (72, 430),
        "You can choose between several translation providers depending on your "
        "needs: Google Translate (free tier), OpenAI GPT-4 "
        "(premium, best for technical content), or Anthropic Claude (premium, "
        "best for literary content).",
        fontsize=11,
    )
    p4.insert_text((72, 540), "For a comparison of providers, see our benchmark report", fontsize=11, color=(0.1, 0.1, 0.8))

    # ============ Page 5: Format Preservation ============
    p5 = doc[4]
    p5.insert_text((72, 80), "4. Format Preservation", fontsize=20, color=(0.1, 0.2, 0.5))
    p5.insert_text(
        (72, 130),
        "Format preservation is a core feature of Office Translator. Unlike raw "
        "translation APIs that return plain text, our platform preserves:",
        fontsize=12,
    )
    features = [
        "Hyperlinks (URLs are kept verbatim; only the visible text is translated)",
        "Footnotes and endnotes (collected, translated, and re-injected)",
        "Cell comments in Excel",
        "Embedded charts (titles, axis labels, category names)",
        "SmartArt diagrams in PowerPoint",
        "Headers, footers, and page numbers",
        "Tables (with formatting and merged cells)",
        "Images (never rasterized away during redaction)",
    ]
    for i, feat in enumerate(features):
        p5.insert_text((90, 180 + i * 25), f"• {feat}", fontsize=11)
    p5.insert_text((72, 400), "For a complete list of supported features, see:", fontsize=11)
    p5.insert_text((72, 420), "https://docs.office-translator.example.com/format-support", fontsize=11, color=(0.1, 0.1, 0.8))
    try:
        from PIL import Image, ImageDraw
        img = Image.new("RGB", (400, 200), color=(255, 255, 255))
        d = ImageDraw.Draw(img)
        d.rectangle([10, 10, 390, 190], outline=(50, 50, 50), width=2)
        d.text((20, 20), "Format preservation: before & after", fill=(0, 0, 0))
        d.rectangle([20, 50, 180, 90], outline=(0, 0, 0))
        d.text((30, 60), "Original", fill=(0, 0, 0))
        d.rectangle([200, 50, 380, 90], outline=(0, 100, 0))
        d.text((220, 60), "Translated", fill=(0, 100, 0))
        buf = io.BytesIO()
        img.save(buf, format="PNG")
        p5.insert_image(fitz.Rect(72, 470, 472, 670), stream=buf.getvalue())
    except ImportError:
        p5.draw_rect(fitz.Rect(72, 470, 472, 670), color=(0.8, 0.9, 0.8), fill=(0.9, 1.0, 0.9))

    # ============ Page 6: Quality Assurance ============
    p6 = doc[5]
    p6.insert_text((72, 80), "5. Quality Assurance", fontsize=20, color=(0.1, 0.2, 0.5))
    p6.insert_text(
        (72, 130),
        "Every translation goes through three quality layers before being "
        "delivered to the user:",
        fontsize=12,
    )
    layers = [
        ("L0 (Pattern detection)", "Detects language confusion, length anomalies, and prompt leaks. No API call."),
        ("L1 (LLM judge)", "Sends 5 sample chunks to a cheap LLM (deepseek-chat) for a binary pass/fail verdict. ~$0.0003/job."),
        ("L2 (Pro judge, 8 dimensions)", "Sends 15 sample chunks to gpt-4o for fine-grained evaluation across accuracy, fluency, terminology, style, completeness, and formatting. ~$0.005/job. Pro+ tier only."),
    ]
    for i, (title, desc) in enumerate(layers):
        y = 180 + i * 80
        p6.insert_text((90, y), title, fontsize=13, color=(0.1, 0.2, 0.5))
        p6.insert_text((90, y + 22), desc, fontsize=11)
    p6.insert_text((72, 460), "5.1 Metrics", fontsize=14, color=(0.1, 0.2, 0.5))
    p6.insert_text(
        (72, 490),
        "All quality scores are exposed as Prometheus metrics for monitoring "
        "and alerting. See the metrics endpoint at /metrics for details.",
        fontsize=11,
    )

    # ============ Page 7: Performance ============
    p7 = doc[6]
    p7.insert_text((72, 80), "6. Performance and Scaling", fontsize=20, color=(0.1, 0.2, 0.5))
    p7.insert_text(
        (72, 130),
        "Office Translator is built on a horizontally scalable architecture. "
        "Translation workers process jobs in parallel, with intelligent caching "
        "to avoid redundant API calls.",
        fontsize=12,
    )
    perf_table_data = [
        ("Document size", "Avg latency (s)", "Throughput (docs/min)"),
        ("< 1 page", "0.4", "150"),
        ("1-5 pages", "1.2", "50"),
        ("5-20 pages", "3.8", "16"),
        ("20-100 pages", "12.5", "5"),
        ("> 100 pages", "45.0", "1"),
    ]
    for i, row in enumerate(perf_table_data):
        y = 200 + i * 25
        for j, cell in enumerate(row):
            color = (0.1, 0.2, 0.5) if i == 0 else (0, 0, 0)
            p7.insert_text((90 + j * 130, y), cell, fontsize=11, color=color)
    p7.insert_text((72, 380), "6.1 Caching", fontsize=14, color=(0.1, 0.2, 0.5))
    p7.insert_text(
        (72, 410),
        "Repeated translations of the same content are served from cache, "
        "reducing API costs by up to 40% on typical workloads. The cache key "
        "includes the user, target language, and any custom prompt/glossary "
        "to avoid cross-contamination.",
        fontsize=11,
    )

    # ============ Page 8: API Reference + Troubleshooting ============
    p8 = doc[7]
    p8.insert_text((72, 80), "7. API Reference", fontsize=20, color=(0.1, 0.2, 0.5))
    p8.insert_text(
        (72, 130),
        "The full API reference is available on our developer portal. Key endpoints:",
        fontsize=12,
    )
    endpoints = [
        ("POST /v1/translate", "Submit a document for translation"),
        ("GET /v1/translations/{id}", "Get the status of a translation job"),
        ("GET /v1/download/{id}", "Download the translated file"),
        ("GET /v1/jobs", "List all jobs for the authenticated user"),
        ("GET /v1/glossaries", "List available glossaries"),
        ("POST /v1/glossaries", "Create a new glossary"),
    ]
    for i, (ep, desc) in enumerate(endpoints):
        y = 180 + i * 30
        p8.insert_text((90, y), ep, fontsize=11, color=(0.1, 0.2, 0.5))
        p8.insert_text((290, y), desc, fontsize=11)
    p8.insert_text((72, 400), "For interactive API documentation, see:", fontsize=11)
    p8.insert_text((72, 420), "https://api.office-translator.example.com/docs", fontsize=11, color=(0.1, 0.1, 0.8))
    p8.insert_text((72, 480), "8. Troubleshooting", fontsize=20, color=(0.1, 0.2, 0.5))
    p8.insert_text(
        (72, 530),
        "Common issues and their solutions are documented in our troubleshooting "
        "guide. If you encounter a problem not covered there, please contact support.",
        fontsize=12,
    )
    p8.insert_text((72, 600), "https://docs.office-translator.example.com/troubleshooting", fontsize=11, color=(0.1, 0.1, 0.8))

    # Add a page header/footer-style band on every page
    for i, page in enumerate(doc):
        page.insert_text(
            (72, 770),
            f"Office Translator v3.0 Technical Specification — Page {i + 1} of {len(doc)}",
            fontsize=8,
            color=(0.5, 0.5, 0.5),
        )

    # Save and re-open — PyMuPDF requires the document to be flushed
    # before we can resolve page references in goto links.
    tmp_path = out.with_suffix(".tmp.pdf")
    doc.save(str(tmp_path))
    doc.close()

    # PHASE 2: add links in a fresh document handle
    doc2 = fitz.open(str(tmp_path))

    # Page 1: TOC gotos + external link
    p1 = doc2[0]
    for i, (label, page_idx_display) in enumerate(toc_entries):
        y = 190 + i * 22
        # PyMuPDF goto uses 0-indexed page numbers.
        # "1. Introduction" is on page 1 in the TOC, which is page index 0 in the PDF.
        target_page_idx = page_idx_display - 1
        p1.insert_link({
            "kind": fitz.LINK_GOTO,
            "from": fitz.Rect(85, y - 12, 420, y + 5),
            "page": target_page_idx,
            "to": fitz.Point(72, 72),
        })
    p1.insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 425, 380, 445),
        "uri": "https://docs.office-translator.example.com/v3",
    })

    # Page 2: pricing external link
    doc2[1].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 280, 470, 300),
        "uri": "https://office-translator.example.com/pricing",
    })

    # Page 3: signup + quickstart links
    doc2[2].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 195, 500, 215),
        "uri": "https://app.office-translator.example.com",
    })
    doc2[2].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 425, 500, 445),
        "uri": "https://docs.office-translator.example.com/v3/quickstart",
    })

    # Page 4: providers link
    doc2[3].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 425, 500, 500),
        "uri": "https://docs.office-translator.example.com/providers",
    })

    # Page 5: format support link
    doc2[4].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 415, 500, 435),
        "uri": "https://docs.office-translator.example.com/format-support",
    })

    # Page 6: metrics docs link
    doc2[5].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 485, 500, 540),
        "uri": "https://docs.office-translator.example.com/metrics",
    })

    # Page 8: API docs + troubleshooting links
    doc2[7].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 415, 500, 435),
        "uri": "https://api.office-translator.example.com/docs",
    })
    doc2[7].insert_link({
        "kind": fitz.LINK_URI,
        "from": fitz.Rect(70, 525, 500, 590),
        "uri": "https://docs.office-translator.example.com/troubleshooting",
    })

    doc2.save(str(out))
    doc2.close()
    tmp_path.unlink()

    # Quick verify
    doc_v = fitz.open(str(out))
    total_links = 0
    total_images = 0
    for p in doc_v:
        total_links += len(p.get_links())
        total_images += len(p.get_images())
    n_pages = len(doc_v)
    doc_v.close()

    print(f"[OK] {out.name}: {out.stat().st_size} bytes")
    print(f"     - Pages: {n_pages}")
    print(f"     - Total hyperlinks: {total_links} (URI + GOTO)")
    print(f"     - Total images: {total_images}")
    print(f"     - Tables, code blocks, TOC, headers/footers")


if __name__ == "__main__":
    print(f"Output directory: {OUT_DIR.resolve()}\n")
    generate_word()
    generate_excel()
    generate_pptx()
    generate_pdf()
    print("\n[OK] Test corpus generated.")
    print("Each file is now substantial enough to catch real format-preservation bugs.")
