#!/usr/bin/env python3
import re, sys
from pathlib import Path
from docx import Document
from docx.enum.section import WD_ORIENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
from docx.shared import Inches, Pt, RGBColor
from docx.oxml import OxmlElement
from docx.oxml.ns import qn

LINK_RE = re.compile(r'(\*\*.*?\*\*|`.*?`|\[.*?\]\([^)]+\)|https?://\S+)')

def hyperlink(paragraph, text, url):
    part = paragraph.part
    rid = part.relate_to(url, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', is_external=True)
    h = OxmlElement('w:hyperlink'); h.set(qn('r:id'), rid)
    r = OxmlElement('w:r'); pr = OxmlElement('w:rPr')
    color = OxmlElement('w:color'); color.set(qn('w:val'), '0563C1'); pr.append(color)
    u = OxmlElement('w:u'); u.set(qn('w:val'), 'single'); pr.append(u)
    r.append(pr); t = OxmlElement('w:t'); t.text = text; r.append(t); h.append(r)
    paragraph._p.append(h)

def add_inline(p, text):
    pos = 0
    for m in LINK_RE.finditer(text):
        if m.start() > pos: p.add_run(text[pos:m.start()])
        s = m.group(0)
        if s.startswith('**'):
            p.add_run(s[2:-2]).bold = True
        elif s.startswith('`'):
            r=p.add_run(s[1:-1]); r.font.name='Consolas'; r.font.size=Pt(10)
        elif s.startswith('['):
            mm=re.match(r'\[(.*?)\]\((.*?)\)',s)
            if mm.group(2).startswith('#'):
                p.add_run(mm.group(1))
            else:
                hyperlink(p,mm.group(1),mm.group(2))
        else:
            url=s.rstrip('.,;:'); hyperlink(p,url,url)
            if len(url)<len(s): p.add_run(s[len(url):])
        pos=m.end()
    if pos < len(text): p.add_run(text[pos:])

def shade(cell, fill):
    tcPr=cell._tc.get_or_add_tcPr(); shd=OxmlElement('w:shd'); shd.set(qn('w:fill'),fill); tcPr.append(shd)

def set_repeat_header(row):
    trPr=row._tr.get_or_add_trPr(); el=OxmlElement('w:tblHeader'); el.set(qn('w:val'),'true'); trPr.append(el)

def set_cell_font_size(cell, points):
    """Set every run in a cell, including runs inside hyperlinks."""
    half_points = str(int(points * 2))
    for run in cell._tc.xpath('.//w:r'):
        rPr = run.find(qn('w:rPr'))
        if rPr is None:
            rPr = OxmlElement('w:rPr')
            run.insert(0, rPr)
        for tag in ('w:sz', 'w:szCs'):
            size = rPr.find(qn(tag))
            if size is None:
                size = OxmlElement(tag)
                rPr.append(size)
            size.set(qn('w:val'), half_points)

def is_sep(line):
    cells=[x.strip() for x in line.strip().strip('|').split('|')]
    return bool(cells) and all(re.fullmatch(r':?-{3,}:?',c or '') for c in cells)

def convert(src, out):
    lines=Path(src).read_text(encoding='utf-8').splitlines()
    doc=Document(); sec=doc.sections[0]
    sec.orientation=WD_ORIENT.LANDSCAPE
    sec.page_width, sec.page_height = Inches(11.7), Inches(8.3)
    sec.top_margin=sec.bottom_margin=Inches(.65); sec.left_margin=sec.right_margin=Inches(.6)
    styles=doc.styles
    styles['Normal'].font.name='Aptos'; styles['Normal'].font.size=Pt(11)
    styles['Normal'].paragraph_format.space_after=Pt(5)
    styles['Title'].font.size=Pt(29)
    for level,size,color in [(1,21,'17365D'),(2,16,'1F4E79'),(3,13,'2F5597')]:
        st=styles[f'Heading {level}']; st.font.name='Aptos Display'; st.font.size=Pt(size); st.font.color.rgb=RGBColor.from_string(color)
        st.paragraph_format.space_before=Pt(10); st.paragraph_format.space_after=Pt(5)
    title_done=False; i=0
    while i<len(lines):
        line=lines[i].rstrip()
        if not line.strip(): i+=1; continue
        if line.startswith('|') and i+1<len(lines) and is_sep(lines[i+1]):
            rows=[]; j=i
            while j<len(lines) and lines[j].startswith('|'):
                if not is_sep(lines[j]): rows.append([x.strip() for x in lines[j].strip().strip('|').split('|')])
                j+=1
            cols=max(len(r) for r in rows); tbl=doc.add_table(rows=len(rows),cols=cols); tbl.style='Table Grid'; tbl.alignment=WD_TABLE_ALIGNMENT.CENTER
            tbl.autofit=True
            for ri,row in enumerate(rows):
                for ci in range(cols):
                    cell=tbl.cell(ri,ci); cell.vertical_alignment=WD_CELL_VERTICAL_ALIGNMENT.CENTER
                    p=cell.paragraphs[0]; p.paragraph_format.space_after=Pt(1)
                    add_inline(p,row[ci] if ci<len(row) else '')
                    set_cell_font_size(cell, 10)
                    if ri==0:
                        shade(cell,'D9EAF7')
                        for run in p.runs: run.bold=True
                if ri==0: set_repeat_header(tbl.rows[0])
            doc.add_paragraph(); i=j; continue
        m=re.match(r'^(#{1,6})\s+(.*)',line)
        if m:
            level=len(m.group(1)); text=m.group(2)
            if level==1 and not title_done:
                p=doc.add_paragraph(); p.style='Title'; p.alignment=WD_ALIGN_PARAGRAPH.CENTER; add_inline(p,text); title_done=True
            else:
                p=doc.add_heading('',level=min(level,3)); add_inline(p,text)
            i+=1; continue
        if re.fullmatch(r'\s*---+\s*',line):
            p=doc.add_paragraph(); pPr=p._p.get_or_add_pPr(); borders=OxmlElement('w:pBdr'); bot=OxmlElement('w:bottom'); bot.set(qn('w:val'),'single'); bot.set(qn('w:sz'),'6'); bot.set(qn('w:color'),'B4C6E7'); borders.append(bot); pPr.append(borders); i+=1; continue
        if line.startswith('>'):
            p=doc.add_paragraph(style='Quote'); add_inline(p,line.lstrip('> ').strip()); i+=1; continue
        m=re.match(r'^\s*[-*]\s+(.*)',line)
        if m:
            p=doc.add_paragraph(style='List Bullet'); add_inline(p,m.group(1)); i+=1; continue
        m=re.match(r'^\s*\d+[.)]\s+(.*)',line)
        if m:
            p=doc.add_paragraph(style='List Number'); add_inline(p,m.group(1)); i+=1; continue
        # Join consecutive prose lines into one paragraph.
        chunk=[line]; i+=1
        while i<len(lines) and lines[i].strip() and not re.match(r'^(#{1,6})\s+|^\||^\s*[-*]\s+|^\s*\d+[.)]\s+|^>|^\s*---+\s*$',lines[i]):
            chunk.append(lines[i].strip()); i+=1
        p=doc.add_paragraph(); add_inline(p,' '.join(chunk))
    doc.core_properties.title='Agent Governance Toolkits: Industry Landscape, Microsoft AGT, and CAF v2 Strategy'
    doc.core_properties.subject='Agent governance landscape and CAF v2 build-versus-reuse strategy'
    doc.core_properties.author='Hermes Agent'
    # Footer with filename.
    sec.footer.paragraphs[0].text='Agent Governance Toolkit Landscape — September 2026'
    sec.footer.paragraphs[0].alignment=WD_ALIGN_PARAGRAPH.CENTER
    for run in sec.footer.paragraphs[0].runs: run.font.size=Pt(9)
    doc.save(out)

if __name__=='__main__':
    if len(sys.argv)!=3: raise SystemExit('usage: md_to_docx.py INPUT.md OUTPUT.docx')
    convert(sys.argv[1],sys.argv[2])
