from pathlib import Path
import re, html
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Preformatted, ListFlowable, ListItem
from reportlab.lib.units import inch

base = Path.home()/'.timmy'/'reports'/'notebooklm'/'2026-03-27-hermes-openclaw'

styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='Body2', parent=styles['BodyText'], fontName='Helvetica', fontSize=10.5, leading=14, spaceAfter=6))
styles.add(ParagraphStyle(name='H1x', parent=styles['Heading1'], fontName='Helvetica-Bold', fontSize=20, leading=24, spaceAfter=12, textColor=colors.HexColor('#111111')))
styles.add(ParagraphStyle(name='H2x', parent=styles['Heading2'], fontName='Helvetica-Bold', fontSize=15, leading=19, spaceBefore=8, spaceAfter=8, textColor=colors.HexColor('#222222')))
styles.add(ParagraphStyle(name='H3x', parent=styles['Heading3'], fontName='Helvetica-Bold', fontSize=12.5, leading=16, spaceBefore=6, spaceAfter=6))
styles.add(ParagraphStyle(name='CodeBlockX', parent=styles['Code'], fontName='Courier', fontSize=8.5, leading=10.5, leftIndent=12, rightIndent=12, backColor=colors.HexColor('#F4F4F4'), borderPadding=6, spaceAfter=8))
styles.add(ParagraphStyle(name='MetaX', parent=styles['BodyText'], fontName='Helvetica-Oblique', fontSize=9.5, leading=12, textColor=colors.HexColor('#555555'), spaceAfter=6))
url_re = re.compile(r'(https?://[^\s)]+)')

def linkify(text: str) -> str:
    esc = html.escape(text)
    return url_re.sub(lambda m: f'<link href="{m.group(1)}" color="blue">{m.group(1)}</link>', esc)

def markdown_to_story(md_path: Path):
    text = md_path.read_text()
    lines = text.splitlines()
    story = []
    i = 0
    while i < len(lines):
        line = lines[i]
        if not line.strip():
            i += 1
            continue
        if line.startswith('```'):
            i += 1
            buf = []
            while i < len(lines) and not lines[i].startswith('```'):
                buf.append(lines[i])
                i += 1
            if i < len(lines) and lines[i].startswith('```'):
                i += 1
            story.append(Preformatted('\n'.join(buf), styles['CodeBlockX']))
            continue
        if line.startswith('# '):
            story.append(Paragraph(linkify(line[2:].strip()), styles['H1x']))
            i += 1
            continue
        if line.startswith('## '):
            story.append(Paragraph(linkify(line[3:].strip()), styles['H2x']))
            i += 1
            continue
        if line.startswith('### '):
            story.append(Paragraph(linkify(line[4:].strip()), styles['H3x']))
            i += 1
            continue
        if re.match(r'^-\s+', line):
            items = []
            while i < len(lines) and re.match(r'^-\s+', lines[i]):
                item_text = re.sub(r'^-\s+', '', lines[i]).strip()
                items.append(ListItem(Paragraph(linkify(item_text), styles['Body2'])))
                i += 1
            story.append(ListFlowable(items, bulletType='bullet', leftIndent=18))
            story.append(Spacer(1, 6))
            continue
        if re.match(r'^\d+\.\s+', line):
            items = []
            while i < len(lines) and re.match(r'^\d+\.\s+', lines[i]):
                item_text = re.sub(r'^\d+\.\s+', '', lines[i]).strip()
                items.append(ListItem(Paragraph(linkify(item_text), styles['Body2'])))
                i += 1
            story.append(ListFlowable(items, bulletType='1', leftIndent=18))
            story.append(Spacer(1, 6))
            continue
        buf = [line.strip()]
        i += 1
        while i < len(lines) and lines[i].strip() and not any([
            lines[i].startswith('# '), lines[i].startswith('## '), lines[i].startswith('### '),
            lines[i].startswith('```'), re.match(r'^-\s+', lines[i]), re.match(r'^\d+\.\s+', lines[i])
        ]):
            buf.append(lines[i].strip())
            i += 1
        paragraph = ' '.join(buf)
        style = styles['MetaX'] if paragraph.startswith('Date:') or paragraph.startswith('Audience:') or paragraph.startswith('Subject:') else styles['Body2']
        story.append(Paragraph(linkify(paragraph), style))
    return story

def add_footer(canvas, doc):
    canvas.saveState()
    canvas.setFont('Helvetica', 8)
    canvas.setFillColor(colors.HexColor('#666666'))
    canvas.drawString(doc.leftMargin, 0.45*inch, f'{doc.title}')
    canvas.drawRightString(letter[0]-doc.rightMargin, 0.45*inch, f'Page {doc.page}')
    canvas.restoreState()

files = [
    ('hermes-agent-backlog-vision-report.md', 'Hermes Agent Research Report'),
    ('openclaw-backlog-vision-report.md', 'OpenClaw Research Report'),
]
for md_name, title in files:
    md_path = base/md_name
    pdf_path = base/md_name.replace('.md', '.pdf')
    story = markdown_to_story(md_path)
    doc = SimpleDocTemplate(str(pdf_path), pagesize=letter, leftMargin=0.7*inch, rightMargin=0.7*inch, topMargin=0.75*inch, bottomMargin=0.7*inch, title=title)
    doc.build(story, onFirstPage=add_footer, onLaterPages=add_footer)

(base/'README.txt').write_text(
    'NotebookLM packet\n\n'
    'Generated files:\n'
    '- hermes-agent-backlog-vision-report.pdf\n'
    '- openclaw-backlog-vision-report.pdf\n\n'
    'Source markdown:\n'
    '- hermes-agent-backlog-vision-report.md\n'
    '- openclaw-backlog-vision-report.md\n'
)

for p in sorted(base.iterdir()):
    print(f'{p.name}\t{p.stat().st_size}')
