#!/usr/bin/env python3
"""Convert tech_digest.html to a styled Economist-style PDF using reportlab."""
import os, re
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY, TA_LEFT
from reportlab.lib.units import inch, cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, PageBreak,
    Table, TableStyle, HRFlowable
)
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.colors import HexColor

OUTPUT = os.path.join(os.path.dirname(__file__), "tech_digest.pdf")
HTML_FILE = os.path.join(os.path.dirname(__file__), "tech_digest.html")

# --- Color palette (Economist-inspired) ---
INK = HexColor("#1a1a1a")
PAPER = HexColor("#faf8f5")
RULE = HexColor("#d4cfc6")
ACCENT = HexColor("#2b2b2b")
SUBTLE = HexColor("#6e6760")
DARK_BG = HexColor("#1a1a1a")
LIGHT_TEXT = HexColor("#faf8f5")

with open(HTML_FILE, "r", encoding="utf-8") as f:
    html_content = f.read()

def strip_tags(text):
    return re.sub(r'<[^>]+>', '', text).strip()

def build_styles():
    s = getSampleStyleSheet()
    styles = {}
    styles['Masthead'] = ParagraphStyle(
        'Masthead', parent=s['Title'], fontSize=28,
        fontName='Helvetica-Bold', textColor=INK,
        alignment=TA_CENTER, spaceAfter=2,
        leading=32
    )
    styles['Tagline'] = ParagraphStyle(
        'Tagline', parent=s['Normal'], fontSize=9,
        fontName='Helvetica', textColor=SUBTLE,
        alignment=TA_CENTER, spaceAfter=8,
        letterSpacing=2.5, textTransform='uppercase'
    )
    styles['DateLine'] = ParagraphStyle(
        'DateLine', parent=s['Normal'], fontSize=10,
        fontName='Helvetica', textColor=SUBTLE,
        alignment=TA_CENTER, spaceAfter=16,
        borderPadding=8
    )
    styles['Intro'] = ParagraphStyle(
        'Intro', parent=s['Normal'], fontSize=12,
        fontName='Times-Roman', textColor=INK,
        alignment=TA_JUSTIFY, leading=17,
        spaceAfter=16, firstLineIndent=0
    )
    styles['SectionHeader'] = ParagraphStyle(
        'SectionHeader', parent=s['Normal'], fontSize=11,
        fontName='Helvetica-Bold', textColor=SUBTLE,
        alignment=TA_CENTER, letterSpacing=3.5,
        textTransform='uppercase', spaceBefore=20,
        spaceAfter=14
    )
    styles['ArticleTitle'] = ParagraphStyle(
        'ArticleTitle', parent=s['Normal'], fontSize=17,
        fontName='Times-Bold', textColor=ACCENT,
        leading=21, spaceAfter=2, spaceBefore=16
    )
    styles['ArticleDateline'] = ParagraphStyle(
        'ArticleDateline', parent=s['Normal'], fontSize=9,
        fontName='Helvetica', textColor=SUBTLE,
        alignment=TA_LEFT, spaceAfter=10,
        letterSpacing=0.8
    )
    styles['LeadPara'] = ParagraphStyle(
        'LeadPara', parent=s['Intro'], fontSize=12,
        fontName='Times-Bold', leading=17,
        spaceAfter=10, firstLineIndent=0
    )
    styles['BodyPara'] = ParagraphStyle(
        'BodyPara', parent=s['Intro'], fontSize=11,
        fontName='Times-Roman', leading=16,
        spaceAfter=10, firstLineIndent=0
    )
    styles['SourceLink'] = ParagraphStyle(
        'SourceLink', parent=s['Normal'], fontSize=9,
        fontName='Helvetica-Oblique', textColor=SUBTLE,
        leading=13, spaceBefore=4, spaceAfter=24
    )
    styles['InsightBox'] = ParagraphStyle(
        'InsightBox', parent=s['Normal'], fontSize=10.5,
        fontName='Times-Roman', textColor=LIGHT_TEXT,
        leading=16, alignment=TA_JUSTIFY, spaceAfter=8
    )
    styles['InsightTitle'] = ParagraphStyle(
        'InsightTitle', parent=s['Normal'], fontSize=9,
        fontName='Helvetica-Bold', textColor=LIGHT_TEXT,
        letterSpacing=2.5, textTransform='uppercase',
        spaceAfter=10, opacity=0.7
    )
    styles['Footer'] = ParagraphStyle(
        'Footer', parent=s['Normal'], fontSize=9,
        fontName='Helvetica', textColor=SUBTLE,
        alignment=TA_CENTER, leading=13
    )
    return styles

def build_document(html):
    doc = SimpleDocTemplate(OUTPUT, pagesize=A4,
                            leftMargin=2*cm, rightMargin=2*cm,
                            topMargin=2.5*cm, bottomMargin=2*cm)
    styles = build_styles()
    story = []

    # Extract sections by finding <h2> headers
    section_pattern = re.compile(
        r'<div class="section-header">\s*<h2>(.*?)</h2>\s*</div>',
        re.DOTALL | re.IGNORECASE
    )
    intro_match = re.search(r'class="intro">(.*?)</section>', html, re.DOTALL)

    # Editor's intro
    if intro_match:
        intro_html = intro_match.group(1)
        intro_text = strip_tags(intro_html)
        story.append(Paragraph(intro_text, styles['Intro']))
        story.append(Spacer(1, 4))

    # Split by sections
    parts = section_pattern.split(html)
    # parts[0] is before first section header (intro area), then alternating section content + next header
    for i in range(1, len(parts) - 1, 2):
        section_title = strip_tags(parts[i])
        article_block = parts[i + 1]

        # Section header
        story.append(HRFlowable(width="100%", thickness=0.5,
                                color=RULE, spaceBefore=8, spaceAfter=4))
        story.append(Paragraph(section_title, styles['SectionHeader']))

        # Parse articles from this section
        article_pattern = re.compile(
            r'<article[^>]*>(.*?)</article>',
            re.DOTALL | re.IGNORECASE
        )
        articles = article_pattern.findall(article_block)

        for art_html in articles:
            title_match = re.search(r'<h3>(.*?)</h3>', art_html, re.DOTALL)
            dateline_match = re.search(r'<div class="dateline">(.*?)</div>', art_html, re.DOTALL)
            paragraphs = re.findall(r'<p[^>]*>(.*?)</p>', art_html, re.DOTALL)

            if title_match:
                story.append(Paragraph(strip_tags(title_match.group(1)),
                                      styles['ArticleTitle']))
            if dateline_match:
                dl_text = strip_tags(dateline_match.group(1))
                story.append(Paragraph(dl_text, styles['ArticleDateline']))

            for p in paragraphs:
                p_clean = re.sub(r'<[^>]+>', '', p).strip()
                if not p_clean:
                    continue
                # Check if it's a lead paragraph (first content para)
                is_lead = (p == paragraphs[0])
                if is_lead and strip_tags(title_match.group(1)):
                    story.append(Paragraph(p_clean, styles['LeadPara']))
                else:
                    story.append(Paragraph(p_clean, styles['BodyPara']))

            # Source link
            source_match = re.search(r'<a[^>]*>(.*?)</a>', art_html[-200:], re.DOTALL)
            if source_match:
                src_text = strip_tags(source_match.group(1))
                story.append(Paragraph(f"Source: {src_text}", styles['SourceLink']))

        # Insight box after articles (if present in section area)
        insight_matches = re.findall(
            r'<div class="insight-box"[^>]*>(.*?)</div>',
            article_block, re.DOTALL | re.IGNORECASE
        )
        for ib_html in insight_matches:
            # Check if it's a dark or light box
            is_dark = 'background: var(--header-bg)' in ib_html or \
                      'background: #1a1a1a' in ib_html
            title_m = re.search(r'<h4[^>]*>(.*?)</h4>', ib_html, re.DOTALL)
            para_matches = re.findall(r'<p[^>]*>(.*?)</p>', ib_html, re.DOTALL)

            story.append(Spacer(1, 8))
            box_data = []
            if title_m:
                title_text = strip_tags(title_m.group(1))
                style = styles['InsightTitle'] if is_dark else \
                    ParagraphStyle('LightInsight', parent=styles['SectionHeader'])
                box_data.append([Paragraph(title_text, style)])
            for pm in para_matches:
                p_clean = re.sub(r'<[^>]+>', '', pm).strip()
                if p_clean:
                    s = styles['InsightBox'] if is_dark else \
                        ParagraphStyle('LightPara', parent=styles['BodyPara'],
                                      textColor=INK)
                    box_data.append([Paragraph(p_clean, s)])

            bg_color = DARK_BG if is_dark else HexColor("#f0ece6")
            text_color = LIGHT_TEXT if is_dark else INK
            t = Table(box_data, colWidths=[15*cm])
            t.setStyle(TableStyle([
                ('BACKGROUND', (0, 0), (-1, -1), bg_color),
                ('TEXTCOLOR', (0, 0), (-1, -1), text_color),
                ('TOPPADDING', (0, 0), (-1, -1), 12),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 12),
                ('LEFTPADDING', (0, 0), (-1, -1), 16),
                ('RIGHTPADDING', (0, 0), (-1, -1), 16),
            ]))
            story.append(t)

    # Footer
    story.append(Spacer(1, 24))
    story.append(HRFlowable(width="100%", thickness=2,
                            color=INK, spaceBefore=8, spaceAfter=4))
    story.append(Paragraph(
        "Compiled by Zuza &nbsp;·&nbsp; Sources linked throughout &nbsp;·&nbsp; Generated 23 July 2026",
        styles['Footer']
    ))

    doc.build(story)
    print(f"PDF written to: {OUTPUT}")
    file_size = os.path.getsize(OUTPUT)
    print(f"File size: {file_size:,} bytes")

if __name__ == "__main__":
    build_document(html_content)
