#!/usr/bin/env python3
"""Push mezcal-varietals.md to Notion as a child page with proper block conversion."""

import json
import re
import requests
import sys
import time

API_KEY = open("/root/.config/notion/api_key").read().strip()
PARENT_PAGE_ID = "29ad6b58-6a7e-80ab-8afb-e2969b81eba8"
NOTION_VERSION = "2022-06-28"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
    "Notion-Version": NOTION_VERSION,
}

def rich_text(text):
    """Convert a string with **bold** and *italic* markdown to Notion rich_text array."""
    if not text:
        return []
    
    segments = []
    # Pattern to find **bold**, *italic*, ***bold+italic***, and `code`
    pattern = r'(\*\*\*(.+?)\*\*\*|\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)'
    
    last_end = 0
    for m in re.finditer(pattern, text):
        # Add plain text before this match
        if m.start() > last_end:
            plain = text[last_end:m.start()]
            if plain:
                segments.append({"type": "text", "text": {"content": plain}})
        
        if m.group(2):  # ***bold+italic***
            segments.append({
                "type": "text",
                "text": {"content": m.group(2)},
                "annotations": {"bold": True, "italic": True}
            })
        elif m.group(3):  # **bold**
            segments.append({
                "type": "text",
                "text": {"content": m.group(3)},
                "annotations": {"bold": True}
            })
        elif m.group(4):  # *italic*
            segments.append({
                "type": "text",
                "text": {"content": m.group(4)},
                "annotations": {"italic": True}
            })
        elif m.group(5):  # `code`
            segments.append({
                "type": "text",
                "text": {"content": m.group(5)},
                "annotations": {"code": True}
            })
        
        last_end = m.end()
    
    # Add remaining plain text
    if last_end < len(text):
        remaining = text[last_end:]
        if remaining:
            segments.append({"type": "text", "text": {"content": remaining}})
    
    if not segments:
        segments.append({"type": "text", "text": {"content": text}})
    
    return segments


def parse_table(lines):
    """Parse markdown table lines into a Notion table block with table_row children."""
    rows = []
    for line in lines:
        line = line.strip()
        if line.startswith('|'):
            line = line[1:]  # remove leading |
        if line.endswith('|'):
            line = line[:-1]  # remove trailing |
        cells = [c.strip() for c in line.split('|')]
        rows.append(cells)
    
    if len(rows) < 2:
        return None
    
    # Check if second row is separator (---|---|---)
    is_separator = all(re.match(r'^[-:]+$', c.strip()) for c in rows[1] if c.strip())
    
    if is_separator:
        header_row = rows[0]
        data_rows = rows[2:]  # skip separator
        has_header = True
    else:
        header_row = rows[0]
        data_rows = rows[1:]
        has_header = False
    
    table_width = len(header_row)
    
    # Build table_row children
    children = []
    
    # Header row
    cells = []
    for cell in header_row:
        cells.append(rich_text(cell))
    children.append({
        "type": "table_row",
        "table_row": {"cells": cells}
    })
    
    # Data rows
    for row in data_rows:
        cells = []
        for i in range(table_width):
            cell_text = row[i] if i < len(row) else ""
            cells.append(rich_text(cell_text))
        children.append({
            "type": "table_row",
            "table_row": {"cells": cells}
        })
    
    table_block = {
        "type": "table",
        "table": {
            "table_width": table_width,
            "has_column_header": has_header,
            "has_row_header": False,
            "children": children
        }
    }
    
    return table_block


def parse_markdown_to_blocks(md_text):
    """Parse the full markdown text into Notion blocks."""
    lines = md_text.split('\n')
    blocks = []
    i = 0
    
    while i < len(lines):
        line = lines[i]
        stripped = line.strip()
        
        # Skip empty lines
        if not stripped:
            i += 1
            continue
        
        # Horizontal rule
        if stripped in ('---', '***', '___') and len(stripped) >= 3:
            blocks.append({"type": "divider", "divider": {}})
            i += 1
            continue
        
        # Headings (map h4+ to h3 since Notion only supports h1-h3)
        heading_match = re.match(r'^(#{1,6})\s+(.+)$', stripped)
        if heading_match:
            level = min(len(heading_match.group(1)), 3)
            text = heading_match.group(2)
            htype = f"heading_{level}"
            blocks.append({
                "type": htype,
                htype: {"rich_text": rich_text(text)}
            })
            i += 1
            continue
        
        # Blockquote
        if stripped.startswith('>'):
            quote_lines = []
            while i < len(lines) and lines[i].strip().startswith('>'):
                quote_text = lines[i].strip()[1:].strip()
                quote_lines.append(quote_text)
                i += 1
            full_quote = '\n'.join(quote_lines)
            blocks.append({
                "type": "quote",
                "quote": {"rich_text": rich_text(full_quote)}
            })
            continue
        
        # Table detection
        if stripped.startswith('|'):
            table_lines = []
            while i < len(lines) and lines[i].strip().startswith('|'):
                table_lines.append(lines[i])
                i += 1
            table_block = parse_table(table_lines)
            if table_block:
                blocks.append(table_block)
            continue
        
        # Bullet list
        bullet_match = re.match(r'^[-*+]\s+(.+)$', stripped)
        if bullet_match:
            text = bullet_match.group(1)
            blocks.append({
                "type": "bulleted_list_item",
                "bulleted_list_item": {"rich_text": rich_text(text)}
            })
            i += 1
            continue
        
        # Regular paragraph
        # Collect consecutive non-special lines as one paragraph
        para_lines = []
        while i < len(lines):
            l = lines[i].strip()
            if not l:
                i += 1
                break
            if l.startswith('#') or l.startswith('>') or l.startswith('|'):
                break
            if re.match(r'^---+$|^\*\*\*+$|^___+$', l):
                break
            if re.match(r'^[-*+]\s+', l):
                break
            para_lines.append(l)
            i += 1
        
        if para_lines:
            full_para = ' '.join(para_lines)
            blocks.append({
                "type": "paragraph",
                "paragraph": {"rich_text": rich_text(full_para)}
            })
        else:
            # Safety valve: if nothing matched and para_lines empty, skip the line
            i += 1
        continue
    
    return blocks


def create_page(parent_id, title, first_blocks):
    """Create a new page in Notion with the first batch of blocks."""
    payload = {
        "parent": {"page_id": parent_id},
        "properties": {
            "title": [{"text": {"content": title}}]
        },
        "children": first_blocks
    }
    
    resp = requests.post(
        "https://api.notion.com/v1/pages",
        headers=HEADERS,
        json=payload
    )
    
    if resp.status_code != 200:
        print(f"ERROR creating page: {resp.status_code}")
        print(resp.text)
        sys.exit(1)
    
    data = resp.json()
    return data["id"], data["url"]


def append_blocks(page_id, blocks):
    """Append blocks to an existing page."""
    payload = {"children": blocks}
    
    resp = requests.patch(
        f"https://api.notion.com/v1/blocks/{page_id}/children",
        headers=HEADERS,
        json=payload
    )
    
    if resp.status_code != 200:
        print(f"ERROR appending blocks: {resp.status_code}")
        print(resp.text)
        return False
    return True


def count_blocks(blocks):
    """Count total blocks including table children (which count toward limit)."""
    # Actually, table children are nested inside the table block itself,
    # so only top-level blocks count toward the 100 limit.
    return len(blocks)


def p(msg):
    print(msg, flush=True)

def main():
    # Read markdown
    with open("/root/clawd/mezcal-varietals.md", "r") as f:
        md_text = f.read()
    
    p("Parsing markdown to Notion blocks...")
    blocks = parse_markdown_to_blocks(md_text)
    total = len(blocks)
    p(f"Total top-level blocks: {total}")
    
    # Batch into groups of 100
    BATCH_SIZE = 100
    batches = [blocks[i:i+BATCH_SIZE] for i in range(0, total, BATCH_SIZE)]
    p(f"Split into {len(batches)} batches")
    
    # Create page with first batch
    title = "Mezcal Agave Varietals & Brands — Full Reference"
    p(f"\nCreating page: {title}")
    p(f"First batch: {len(batches[0])} blocks")
    
    page_id, page_url = create_page(PARENT_PAGE_ID, title, batches[0])
    p(f"Page created! ID: {page_id}")
    p(f"URL: {page_url}")
    
    # Append remaining batches
    for idx, batch in enumerate(batches[1:], start=2):
        p(f"\nAppending batch {idx}/{len(batches)} ({len(batch)} blocks)...")
        time.sleep(0.5)  # Rate limit courtesy
        success = append_blocks(page_id, batch)
        if success:
            p(f"Batch {idx} appended successfully.")
        else:
            p(f"Batch {idx} FAILED. Stopping.")
            break
    
    p(f"\n✅ Done! Page URL: {page_url}")


if __name__ == "__main__":
    main()
