from pathlib import Path
import re, subprocess, shutil
from docx import Document
from docx.shared import Cm, Pt, RGBColor
from docx.enum.section import WD_SECTION
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
from docx.oxml import OxmlElement
from docx.oxml.ns import qn

BASE=Path('/home/agent/outputs/moenchaltorf_fachplaner_jourfix_2_20260707')
DRAFT=BASE/'draft'
ART=BASE/'artifacts'
ART.mkdir(exist_ok=True)
TEMPLATE=Path('/home/agent/jarvis_memory/work/projects/moenchaltorf/documents/source_files/01 Protokollvorlage FPS/260623_Moenchaltorf_Protokoll_1_Fachplaner_Jourfixe_ERNE_CD_fina (1).docx')
BLUE='365294'
BEIGE='E2D3C4'
LIGHT='F6F1EC'

def set_cell_shading(cell, fill):
    tcPr = cell._tc.get_or_add_tcPr()
    shd = tcPr.find(qn('w:shd'))
    if shd is None:
        shd = OxmlElement('w:shd')
        tcPr.append(shd)
    shd.set(qn('w:fill'), fill)

def set_cell_text_color(cell, rgb):
    for p in cell.paragraphs:
        for run in p.runs:
            run.font.color.rgb = RGBColor.from_string(rgb)

def no_row_split(row):
    trPr = row._tr.get_or_add_trPr()
    cant = OxmlElement('w:cantSplit')
    trPr.append(cant)

def style_doc(doc):
    sec=doc.sections[0]
    sec.page_width=Cm(21.0); sec.page_height=Cm(29.7)
    sec.top_margin=Cm(2.35); sec.bottom_margin=Cm(1.85)
    sec.left_margin=Cm(1.65); sec.right_margin=Cm(1.65)
    sec.header_distance=Cm(0.85); sec.footer_distance=Cm(0.85)
    styles=doc.styles
    styles['Normal'].font.name='Arial'; styles['Normal'].font.size=Pt(8.5)
    for s, size in [('Heading 1',16),('Heading 2',13),('Heading 3',10)]:
        try:
            styles[s].font.name='Arial'
            styles[s].font.color.rgb=RGBColor.from_string(BLUE)
            styles[s].font.size=Pt(size)
        except KeyError:
            pass
    # If an ERNE protocol template is available, keep its header/footer with
    # ERNE logo, top-right design graphic and page-number footer intact.
    if not TEMPLATE.exists():
        footer=sec.footer.paragraphs[0]
        footer.text='ERNE AG Holzbau | Mönchaltorf – Gemeindehaus mit Wohnbau | www.erne.net'
        footer.alignment=WD_ALIGN_PARAGRAPH.CENTER
        for r in footer.runs:
            r.font.name='Arial'; r.font.size=Pt(7); r.font.color.rgb=RGBColor.from_string(BLUE)

def clear_body_keep_section(doc):
    body = doc._body._element
    sectPr = None
    for child in list(body):
        if child.tag == qn('w:sectPr'):
            sectPr = child
        else:
            body.remove(child)
    if sectPr is not None and sectPr.getparent() is None:
        body.append(sectPr)

def add_md_table(doc, lines):
    rows=[]
    for line in lines:
        s=line.strip()
        if not s.startswith('|'): continue
        cells=[c.strip() for c in s.strip('|').split('|')]
        if all(re.fullmatch(r':?-{3,}:?', c.replace(' ','')) for c in cells):
            continue
        rows.append(cells)
    if not rows: return
    maxcols=max(len(r) for r in rows)
    table=doc.add_table(rows=len(rows), cols=maxcols)
    table.alignment=WD_TABLE_ALIGNMENT.CENTER
    try:
        table.style='Table Grid'
    except KeyError:
        pass
    for i,row in enumerate(rows):
        no_row_split(table.rows[i])
        for j in range(maxcols):
            cell=table.cell(i,j)
            cell.vertical_alignment=WD_CELL_VERTICAL_ALIGNMENT.TOP
            cell.text=row[j] if j < len(row) else ''
            for p in cell.paragraphs:
                p.paragraph_format.space_after=Pt(0)
                for run in p.runs:
                    run.font.name='Arial'; run.font.size=Pt(8)
            if i==0:
                set_cell_shading(cell, BLUE); set_cell_text_color(cell, 'FFFFFF')
            elif i%2==0:
                set_cell_shading(cell, LIGHT)
    doc.add_paragraph('')

def add_formatted_para(doc, text, style=None):
    try:
        p=doc.add_paragraph(style=style) if style else doc.add_paragraph()
    except KeyError:
        p=doc.add_paragraph()
    # simple bold **...** support
    parts=re.split(r'(\*\*.*?\*\*)', text)
    for part in parts:
        if part.startswith('**') and part.endswith('**'):
            run=p.add_run(part[2:-2]); run.bold=True
        else:
            p.add_run(part)
    for r in p.runs:
        r.font.name='Arial'
        if style is None: r.font.size=Pt(8.5)
    if style and style.startswith('Heading'):
        p.paragraph_format.keep_with_next=True
        p.paragraph_format.space_before=Pt(8); p.paragraph_format.space_after=Pt(4)
        # User QA: avoid orphaned section headings shortly before page breaks.
        # These sections must start cleanly on a new page in the ERNE protocol.
        if text.strip() == 'Ampelstatus' or text.strip().startswith('6. Bauphysik / Schallschutz'):
            p.paragraph_format.page_break_before = True
        size = {'Heading 1':16, 'Heading 2':13, 'Heading 3':10}.get(style, 10)
        for r in p.runs:
            r.font.name='Arial'; r.font.size=Pt(size); r.font.color.rgb=RGBColor.from_string(BLUE); r.bold=True
    else:
        p.paragraph_format.space_after=Pt(3)
    return p

def md_to_docx(md_path, docx_path, title_override=None):
    doc=Document(str(TEMPLATE)) if TEMPLATE.exists() else Document()
    if TEMPLATE.exists():
        clear_body_keep_section(doc)
    style_doc(doc)
    lines=md_path.read_text(encoding='utf-8').splitlines()
    i=0
    while i < len(lines):
        line=lines[i].rstrip()
        if not line.strip() or line.strip()=='---':
            i+=1; continue
        if line.startswith('|'):
            tbl=[]
            while i < len(lines) and lines[i].strip().startswith('|'):
                tbl.append(lines[i]); i+=1
            add_md_table(doc,tbl); continue
        if line.startswith('# '):
            p=add_formatted_para(doc,line[2:].strip(),'Heading 1'); p.alignment=WD_ALIGN_PARAGRAPH.CENTER
        elif line.startswith('## '):
            add_formatted_para(doc,line[3:].strip(),'Heading 2')
        elif line.startswith('#### '):
            add_formatted_para(doc,line[5:].strip(),'Heading 3')
        elif line.startswith('### '):
            add_formatted_para(doc,line[4:].strip(),'Heading 3')
        elif line.startswith('- '):
            p=add_formatted_para(doc,'• ' + line[2:].strip(),None)
        elif re.match(r'^\d+\.\s', line):
            p=add_formatted_para(doc,line.strip(),None)
        else:
            add_formatted_para(doc,line,None)
        i+=1
    doc.save(docx_path)

files=[('bereinigtes_transkript.md','260707_Moenchaltorf_Transkript_2_Fachplaner_Jourfixe.docx'),('protokoll.md','260707_Moenchaltorf_Protokoll_2_Fachplaner_Jourfixe.docx')]
for md,docx in files:
    md_to_docx(DRAFT/md, ART/docx)

# Convert to PDF
lo=shutil.which('libreoffice') or shutil.which('soffice')
if not lo:
    raise SystemExit('LibreOffice not found')
for _,docx in files:
    subprocess.run([lo,'--headless','--convert-to','pdf','--outdir',str(ART),str(ART/docx)], check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print('created')
for p in sorted(ART.iterdir()):
    print(p, p.stat().st_size)
