#!/usr/bin/env python3
"""Convert the Core Charge operations guide (Markdown) into a styled Word .docx."""
import os
import re
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT

BASE = os.path.dirname(os.path.abspath(__file__))
MD = os.path.join(BASE, "Core-Charge-Operations-Guide.md")
OUT = os.path.join(BASE, "Core-Charge-Operations-Guide.docx")

ACCENT = RGBColor(0xC2, 0x41, 0x0C)   # orange (matches the Core Charge button)
GREY = RGBColor(0x6B, 0x72, 0x80)

doc = Document()

# Base font
style = doc.styles["Normal"]
style.font.name = "Calibri"
style.font.size = Pt(11)

# Heading colors
for h, size in (("Heading 1", 18), ("Heading 2", 14), ("Heading 3", 12)):
    st = doc.styles[h]
    st.font.color.rgb = ACCENT if h != "Heading 1" else RGBColor(0x1F, 0x29, 0x37)
    st.font.size = Pt(size)
    st.font.name = "Calibri"


def add_runs(paragraph, text):
    """Render inline **bold**, `code`, and emoji/plain text into runs."""
    # split on bold and inline code while keeping delimiters
    tokens = re.split(r"(\*\*.+?\*\*|`.+?`)", text)
    for tok in tokens:
        if not tok:
            continue
        if tok.startswith("**") and tok.endswith("**"):
            r = paragraph.add_run(tok[2:-2])
            r.bold = True
        elif tok.startswith("`") and tok.endswith("`"):
            r = paragraph.add_run(tok[1:-1])
            r.font.name = "Consolas"
            r.font.size = Pt(10)
            r.font.color.rgb = ACCENT
        else:
            paragraph.add_run(tok)


def flush_table(rows):
    if not rows:
        return
    # rows: list of list-of-cell-strings; row 0 is header, row 1 is the --- separator
    header = rows[0]
    body = [r for r in rows[2:]] if len(rows) > 2 else []
    table = doc.add_table(rows=1, cols=len(header))
    table.style = "Light Grid Accent 2"
    table.alignment = WD_TABLE_ALIGNMENT.LEFT
    hdr = table.rows[0].cells
    for i, cell_text in enumerate(header):
        hdr[i].text = ""
        p = hdr[i].paragraphs[0]
        add_runs(p, cell_text.strip())
        for run in p.runs:
            run.bold = True
    for row in body:
        cells = table.add_row().cells
        for i, cell_text in enumerate(row):
            if i >= len(cells):
                continue
            cells[i].text = ""
            add_runs(cells[i].paragraphs[0], cell_text.strip())
    doc.add_paragraph()


def parse_table_row(line):
    line = line.strip()
    if line.startswith("|"):
        line = line[1:]
    if line.endswith("|"):
        line = line[:-1]
    return [c.strip() for c in line.split("|")]


with open(MD, encoding="utf-8") as f:
    lines = f.read().splitlines()

i = 0
in_code = False
code_lines = []
table_rows = []

while i < len(lines):
    line = lines[i]

    # code fences
    if line.strip().startswith("```"):
        if in_code:
            # close
            p = doc.add_paragraph()
            run = p.add_run("\n".join(code_lines))
            run.font.name = "Consolas"
            run.font.size = Pt(9.5)
            # light shading via paragraph border is complex; keep monospace
            code_lines = []
            in_code = False
        else:
            in_code = True
        i += 1
        continue
    if in_code:
        code_lines.append(line)
        i += 1
        continue

    # tables
    if line.strip().startswith("|"):
        table_rows.append(parse_table_row(line))
        i += 1
        # if next line is not a table row, flush
        if i >= len(lines) or not lines[i].strip().startswith("|"):
            flush_table(table_rows)
            table_rows = []
        continue

    stripped = line.strip()

    # horizontal rule
    if stripped == "---":
        i += 1
        continue

    # images: ![alt](path)
    m = re.match(r"!\[(.*?)\]\((.*?)\)", stripped)
    if m:
        alt, path = m.group(1), m.group(2)
        img_path = os.path.join(BASE, path)
        if os.path.exists(img_path):
            doc.add_picture(img_path, width=Inches(6.0))
            doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
        i += 1
        continue

    # headings
    if stripped.startswith("# "):
        doc.add_heading(stripped[2:].strip(), level=1)
        i += 1
        continue
    if stripped.startswith("## "):
        doc.add_heading(stripped[3:].strip(), level=2)
        i += 1
        continue
    if stripped.startswith("### "):
        doc.add_heading(stripped[4:].strip(), level=3)
        i += 1
        continue

    # blockquote
    if stripped.startswith(">"):
        text = stripped.lstrip(">").strip()
        p = doc.add_paragraph()
        p.paragraph_format.left_indent = Inches(0.3)
        add_runs(p, text)
        for r in p.runs:
            r.italic = True
            r.font.color.rgb = GREY
        i += 1
        continue

    # bullets
    if stripped.startswith(("- ", "* ", "✅", "🚫", "💳")):
        text = stripped
        for pre in ("- ", "* "):
            if text.startswith(pre):
                text = text[len(pre):]
                break
        p = doc.add_paragraph(style="List Bullet")
        add_runs(p, text)
        i += 1
        continue

    # numbered list
    nm = re.match(r"^(\d+)\.\s+(.*)", stripped)
    if nm:
        p = doc.add_paragraph(style="List Number")
        add_runs(p, nm.group(2))
        i += 1
        continue

    # blank
    if stripped == "":
        i += 1
        continue

    # normal paragraph
    p = doc.add_paragraph()
    add_runs(p, stripped)
    i += 1

doc.save(OUT)
print("Wrote", OUT)
