"""Generate an editable PPTX presentation for Dobby."""
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
import os

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

# Colors
INDIGO = RGBColor(99, 102, 241)
DARK = RGBColor(26, 26, 46)
MUTED = RGBColor(74, 85, 104)
LIGHT_BG = RGBColor(250, 250, 250)
WHITE = RGBColor(255, 255, 255)
GREEN = RGBColor(34, 197, 94)
AMBER = RGBColor(234, 179, 8)
RED = RGBColor(248, 113, 113)
BLUE = RGBColor(59, 130, 246)
LIGHT_GRAY = RGBColor(226, 232, 240)

def add_slide(title_text=None, layout_idx=6):
    """Add a blank slide with optional title."""
    slide = prs.slides.add_slide(prs.slide_layouts[layout_idx])
    # Background
    bg = slide.background
    fill = bg.fill
    fill.solid()
    fill.fore_color.rgb = LIGHT_BG
    return slide

def add_text(slide, left, top, width, height, text, size=18, bold=False, color=DARK, align=PP_ALIGN.LEFT, font_name='Calibri'):
    txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = text
    p.font.size = Pt(size)
    p.font.bold = bold
    p.font.color.rgb = color
    p.font.name = font_name
    p.alignment = align
    return txBox

def add_bullet(slide, left, top, width, height, items, size=16, color=DARK):
    txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
    tf = txBox.text_frame
    tf.word_wrap = True
    for i, item in enumerate(items):
        if i == 0:
            p = tf.paragraphs[0]
        else:
            p = tf.add_paragraph()
        p.text = item
        p.font.size = Pt(size)
        p.font.color.rgb = color
        p.font.name = 'Calibri'
        p.space_after = Pt(6)
        p.level = 0
    return txBox

# ============================================
# SLIDE 1: Title
# ============================================
s = add_slide()
add_text(s, 1.5, 1.5, 10, 1.2, "Dobby", size=48, bold=True, color=INDIGO, align=PP_ALIGN.CENTER)
add_text(s, 1.5, 2.7, 10, 0.8, "A Distributed Meta-Agent Orchestrator for Research", size=24, color=DARK, align=PP_ALIGN.CENTER)
add_text(s, 1.5, 3.8, 10, 0.5, "From one agent on one machine → parallel agents across your entire infrastructure", size=16, color=MUTED, align=PP_ALIGN.CENTER)
add_text(s, 1.5, 5.5, 10, 0.4, "Simon Yu  ·  March 2026", size=14, color=MUTED, align=PP_ALIGN.CENTER)

# Add Dobby image if available
img_path = os.path.join(os.path.dirname(__file__), '..', 'assets', 'dobby.png')
if os.path.exists(img_path):
    s.shapes.add_picture(img_path, Inches(5.9), Inches(4.3), Inches(1.2))

# ============================================
# SLIDE 2: The Problem
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "The Serialization Bottleneck", size=36, bold=True, color=DARK)

add_text(s, 0.8, 1.6, 5, 0.5, "We have powerful tools:", size=20, bold=True, color=DARK)
add_bullet(s, 0.8, 2.2, 5.5, 2.5, [
    "🤖  Claude Code — autonomous coding agent",
    "🔧  Codex — OpenAI's coding agent",
    "⚡  GPU clusters — EC2, university HPC, local machines",
    "📂  Multiple projects — papers, experiments, infrastructure",
], size=16, color=MUTED)

add_text(s, 7, 1.6, 5.5, 0.5, "But we are the bottleneck:", size=20, bold=True, color=RED)
add_bullet(s, 7, 2.2, 5.5, 2.5, [
    "❌  One experiment at a time",
    "❌  One machine at a time",
    "❌  Must actively watch it",
    "❌  Sleep = everything stops",
    "❌  Context-switching wastes hours",
], size=16, color=MUTED)

# Quote box
shape = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(2), Inches(5.2), Inches(9), Inches(1))
shape.fill.solid()
shape.fill.fore_color.rgb = RGBColor(238, 242, 255)
shape.line.color.rgb = INDIGO
shape.line.width = Pt(2)
add_text(s, 2.3, 5.35, 8.5, 0.7, '"The bottleneck in research isn\'t intelligence — it\'s coordination."', size=20, bold=False, color=INDIGO, align=PP_ALIGN.CENTER)

# ============================================
# SLIDE 3: Solution
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "Dobby: Your AI Engineering Manager", size=36, bold=True, color=DARK)
add_text(s, 0.8, 1.4, 11, 0.5, "A meta-agent that manages coding agents the way a manager manages engineers", size=18, color=MUTED)

cards = [
    ("📱", "Submit from Anywhere", "Slack, MCP, CLI, API — even from your phone"),
    ("🌐", "Distribute Across Machines", "Mac, EC2 GPU, HPC cluster — in parallel"),
    ("🔄", "Monitor 24/7", "Catches failures, auto-debugs, resubmits"),
    ("📊", "Report Results", "Dashboard, Slack notifications, Flow view"),
]
for i, (icon, title, desc) in enumerate(cards):
    x = 0.8 + (i % 2) * 6
    y = 2.4 + (i // 2) * 2.2
    shape = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(5.5), Inches(1.8))
    shape.fill.solid()
    shape.fill.fore_color.rgb = WHITE
    shape.line.color.rgb = LIGHT_GRAY
    add_text(s, x + 0.3, y + 0.2, 4.8, 0.5, f"{icon}  {title}", size=22, bold=True, color=DARK)
    add_text(s, x + 0.3, y + 0.9, 4.8, 0.6, desc, size=16, color=MUTED)

# ============================================
# SLIDE 4: Architecture (placeholder for draw.io)
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "Architecture Overview", size=36, bold=True, color=DARK)
# Check for exported PNG
arch_img = os.path.join(os.path.dirname(__file__), 'architecture.drawio.png')
if os.path.exists(arch_img):
    s.shapes.add_picture(arch_img, Inches(1), Inches(1.5), Inches(11))
else:
    add_text(s, 2, 3, 9, 1, "[Insert architecture.drawio.png here]", size=24, color=MUTED, align=PP_ALIGN.CENTER)
    add_text(s, 2, 4.2, 9, 0.5, "Export from draw.io and re-run this script", size=14, color=MUTED, align=PP_ALIGN.CENTER)

# ============================================
# SLIDE 5: Comparison
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "How Dobby Differs", size=36, bold=True, color=DARK)

# Table
rows = 7
cols = 4
tbl = s.shapes.add_table(rows, cols, Inches(0.8), Inches(1.5), Inches(11.5), Inches(5)).table
tbl.columns[0].width = Inches(2.5)
tbl.columns[1].width = Inches(3)
tbl.columns[2].width = Inches(3)
tbl.columns[3].width = Inches(3)

headers = ["", "Claude Code / Codex", "OpenHands / OpenClaw", "Dobby"]
data = [
    ["Machines", "1", "1", "N (distributed)"],
    ["Always-on", "❌ Dies with terminal", "❌ Dies with browser", "✅ VPS hub 24/7"],
    ["Submit from", "Terminal only", "Browser only", "Slack / MCP / CLI / API"],
    ["Backends", "Claude only / OpenAI only", "OpenAI only", "Claude + Codex"],
    ["Overnight", "❌", "❌", "✅ Self-healing"],
    ["Approval flow", "❌ Fully interactive", "❌ Fully autonomous", "✅ Plan → Approve → Execute"],
]

for ci, h in enumerate(headers):
    cell = tbl.cell(0, ci)
    cell.text = h
    for p in cell.text_frame.paragraphs:
        p.font.size = Pt(14)
        p.font.bold = True
        p.font.color.rgb = WHITE
    cell.fill.solid()
    cell.fill.fore_color.rgb = INDIGO if ci == 3 else RGBColor(100, 116, 139)

for ri, row in enumerate(data):
    for ci, val in enumerate(row):
        cell = tbl.cell(ri + 1, ci)
        cell.text = val
        for p in cell.text_frame.paragraphs:
            p.font.size = Pt(13)
            p.font.color.rgb = DARK
            p.font.bold = ci == 0
        if ci == 3:
            cell.fill.solid()
            cell.fill.fore_color.rgb = RGBColor(238, 242, 255)

# ============================================
# SLIDE 6: Recursive Agents
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "Recursive Agent Dispatch", size=36, bold=True, color=DARK)
add_text(s, 0.8, 1.4, 11, 0.5, "Each agent can call Dobby (via MCP) to create more sub-tasks — unlimited delegation depth", size=18, color=MUTED)

recur_img = os.path.join(os.path.dirname(__file__), 'recursive-agents.drawio.png')
if os.path.exists(recur_img):
    s.shapes.add_picture(recur_img, Inches(1.5), Inches(2.2), Inches(10))
else:
    add_text(s, 2, 3.5, 9, 1, "[Insert recursive-agents.drawio.png here]", size=24, color=MUTED, align=PP_ALIGN.CENTER)

# ============================================
# SLIDE 7: Overnight Example
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "Overnight Autonomy — Real Example", size=36, bold=True, color=DARK)

timeline = [
    ("10:00 PM", "Submit 6 tasks across 3 projects via Slack. Go to sleep.", MUTED),
    ("2:00 AM", "Dobby detects vLLM crash (OOM) → diagnoses root cause → resubmits with fix", RED),
    ("6:00 AM", "Pipeline completes → Dobby pivots to Inverse-IFEval training → submits 3 jobs", AMBER),
    ("8:00 AM", "Morning summary posted to Slack with all results", GREEN),
]

for i, (time, desc, color) in enumerate(timeline):
    y = 1.8 + i * 1.1
    # Time pill
    shape = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.8), Inches(y), Inches(1.8), Inches(0.7))
    shape.fill.solid()
    shape.fill.fore_color.rgb = color
    shape.line.fill.background()
    add_text(s, 0.85, y + 0.1, 1.7, 0.5, time, size=16, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
    # Description
    add_text(s, 3, y + 0.1, 9.5, 0.6, desc, size=16, color=DARK)

# Results box
shape = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(3), Inches(5.8), Inches(7), Inches(1.2))
shape.fill.solid()
shape.fill.fore_color.rgb = WHITE
shape.line.color.rgb = GREEN
shape.line.width = Pt(2)
add_text(s, 3.3, 5.9, 6.5, 0.9, "✅ Meta-Agent: Research report + experiments\n✅ ADPO: Gemma HaluEval + 3 models IFEval\n✅ SPARE: 3 slurm jobs running\n\nTotal overnight cost: ~$12", size=14, color=DARK)

# ============================================
# SLIDE 8: Dashboard
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "Live Dashboard", size=36, bold=True, color=DARK)
add_text(s, 0.8, 1.3, 11, 0.4, "https://dobby.chats-lab-gui-agent.uk/dashboard", size=16, color=BLUE, align=PP_ALIGN.CENTER)

features = [
    ("🌐", "Agent Network", "Hub + spokes with live status dots"),
    ("📊", "Contribution Heatmap", "GitHub-style, 30 days, per-project"),
    ("🔄", "Flow View", "VibeLens-style agent execution timeline"),
    ("📈", "Usage Tracking", "Claude API utilization over time (SVG chart)"),
    ("🎯", "Project Control", "Per-project status with spoke labels"),
    ("📝", "Docs", "Changelog + Wishlist, rendered from markdown"),
]
for i, (icon, title, desc) in enumerate(features):
    x = 0.8 + (i % 3) * 4
    y = 2.2 + (i // 3) * 2.2
    shape = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(3.6), Inches(1.8))
    shape.fill.solid()
    shape.fill.fore_color.rgb = WHITE
    shape.line.color.rgb = LIGHT_GRAY
    add_text(s, x + 0.2, y + 0.2, 3.2, 0.4, f"{icon}  {title}", size=18, bold=True, color=DARK)
    add_text(s, x + 0.2, y + 0.8, 3.2, 0.7, desc, size=14, color=MUTED)

# ============================================
# SLIDE 9: What's Next
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "What's Next", size=36, bold=True, color=DARK)

sections = [
    ("High Priority", INDIGO, [
        "🖼️  Image generation — Gemini API / diagrams on demand",
        "📊  Presentation builder — auto-generate slides from results",
        "📅  Calendar integration — deadline reminders, scheduling",
    ]),
    ("Architecture", BLUE, [
        "⚡  Parallel spoke execution — multiple agents per machine",
        "🧠  Smart task routing — auto-select machine by requirements",
        "💬  Dashboard chat — ask questions with project context",
    ]),
    ("Scale", GREEN, [
        "👥  Multi-user support — shared dashboard, role-based access",
        "🔄  Agent collaboration — agents working together on tasks",
        "📱  Mobile app — push notifications, quick actions",
    ]),
]
for i, (title, color, items) in enumerate(sections):
    x = 0.8 + i * 4.1
    add_text(s, x, 1.5, 3.8, 0.5, title, size=20, bold=True, color=color)
    add_bullet(s, x, 2.2, 3.8, 4, items, size=13, color=MUTED)

# ============================================
# SLIDE 10: Summary
# ============================================
s = add_slide()
add_text(s, 0.8, 0.5, 11, 0.8, "Summary", size=36, bold=True, color=DARK)

# Key quote
shape = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(1.5), Inches(1.5), Inches(10), Inches(1.2))
shape.fill.solid()
shape.fill.fore_color.rgb = RGBColor(238, 242, 255)
shape.line.color.rgb = INDIGO
shape.line.width = Pt(2)
add_text(s, 1.8, 1.65, 9.5, 0.9, "Claude Code is the engineer.\nDobby is the engineering manager.", size=24, bold=True, color=INDIGO, align=PP_ALIGN.CENTER)

add_bullet(s, 1.5, 3.2, 10, 3, [
    "✅  Distributed execution across N machines (Mac, EC2 GPU, HPC cluster)",
    "✅  Always-on VPS hub — submit from Slack, MCP, CLI, anywhere",
    "✅  Plan → Approve → Execute — right level of autonomy",
    "✅  Self-healing overnight runs — catches failures, auto-debugs",
    "✅  Full observability — dashboard, Flow view, utilization tracking",
    "✅  Backend-agnostic — Claude Code + Codex on same task queue",
], size=16, color=DARK)

add_text(s, 1.5, 6.2, 10, 0.4, "🔗  github.com/simonucl/dobby", size=16, color=BLUE, align=PP_ALIGN.CENTER)

# Save
out = os.path.join(os.path.dirname(__file__), 'slides_editable.pptx')
prs.save(out)
print(f"Saved to {out}")
