#!/usr/bin/env python3
"""Visual QA test deck generator for pptx-mcp.

Generates ~12 PPTX files into test_output/ covering all 32 slide types,
12 chart types, 8 diagram types, brand presets, and designer features.
Open the output in PowerPoint/Keynote for visual inspection.

Usage:
    .venv/bin/python scripts/generate_test_decks.py
"""

from __future__ import annotations

import json
import sys
import time
from pathlib import Path

# Ensure project root is on sys.path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT))

from pptx_mcp.agents.planner import PlannerInput, SlidePlannerAgent
from pptx_mcp.brand.defaults import get_preset
from pptx_mcp.engine.brand_extractor import extract_brand
from pptx_mcp.engine.brand_guide import generate_brand_guide
from pptx_mcp.engine.generator import DeckGenerator
from pptx_mcp.engine.spec_parser import parse_spec
from pptx_mcp.models.brand import BrandConfig, ShapeStyleConfig
from pptx_mcp.models.diagrams import (
    CycleStep,
    GanttTask,
    MatrixData,
    MatrixQuadrant,
    OrgNode,
    PyramidLayer,
    SpokeItem,
    VennCircle,
    VennData,
    WaterfallBar,
)
from pptx_mcp.models.slides import (
    AgendaItem,
    BubbleChartDataModel,
    BubbleDataPoint,
    BubbleDataSeries,
    CalloutBox,
    CardDefinition,
    Badge,
    ChartData,
    ChartDataSeries,
    ChartElement,
    ChartType,
    ColumnContent,
    FunnelStage,
    IconItem,
    KpiCard,
    PresentationDefinition,
    PresentationMetadata,
    ProcessStep,
    SlideDefinition,
    SlideType,
    SwotData,
    TableCell,
    TableElement,
    TeamMember,
    TextStyle,
    XyChartData,
    XyDataPoint,
    XyDataSeries,
)
from pptx_mcp.review.engine import ReviewEngine

# ---------------------------------------------------------------------------
# Mock content data — consistent fictional company
# ---------------------------------------------------------------------------

COMPANY = "Meridian Technologies"
TOPIC = "Cloud Infrastructure Modernization"
AUDIENCE = "executive"
KEY_POINTS = [
    "42% reduction in infrastructure costs over 18 months",
    "Migration of 156 microservices to Kubernetes",
    "99.99% uptime SLA achieved in Q3",
    "3 phased rollout: foundation, migration, optimization",
    "$4.2M annual savings projected by Year 2",
    "Team expanded from 12 to 28 engineers",
    "NPS score improved from 34 to 71",
    "Zero-downtime deployment pipeline shipping 47 releases per week",
]


def _meta(title: str) -> PresentationMetadata:
    return PresentationMetadata(
        title=title,
        author="Test Suite",
        company=COMPANY,
        date="2026-02-13",
    )


# ---------------------------------------------------------------------------
# 01 — Kitchen Sink: all 32 slide types
# ---------------------------------------------------------------------------

def generate_kitchen_sink(output_dir: Path) -> Path:
    """Generate a deck containing all 32 slide types with mock data."""
    slides: list[SlideDefinition] = []

    # TITLE
    slides.append(SlideDefinition(
        slide_type=SlideType.TITLE,
        title="Kitchen Sink Test Deck",
        subtitle="All 32 slide types in one file",
    ))

    # SECTION
    slides.append(SlideDefinition(
        slide_type=SlideType.SECTION,
        title="Section Break",
        subtitle="Core slide types",
    ))

    # CONTENT
    slides.append(SlideDefinition(
        slide_type=SlideType.CONTENT,
        title="Content Slide",
        bullets=["First key point about infrastructure", "Second point on migration strategy",
                 "Third point covering timeline", "Fourth point on budget allocation"],
    ))

    # TWO_COLUMN
    slides.append(SlideDefinition(
        slide_type=SlideType.TWO_COLUMN,
        title="Two-Column Layout",
        columns=[
            ColumnContent(title="Current State", bullets=["Legacy monolith", "Manual deployments", "High latency"]),
            ColumnContent(title="Future State", bullets=["Microservices", "CI/CD pipeline", "Sub-100ms response"]),
        ],
    ))

    # PROS_CONS
    slides.append(SlideDefinition(
        slide_type=SlideType.PROS_CONS,
        title="Cloud Migration Trade-offs",
        pros=["Scalability on demand", "Cost optimization", "Global availability"],
        cons=["Initial migration cost", "Team retraining", "Vendor lock-in risk"],
    ))

    # CHART (bar)
    slides.append(SlideDefinition(
        slide_type=SlideType.CHART,
        title="Quarterly Revenue",
        elements=[ChartElement(
            chart_type=ChartType.BAR,
            data=ChartData(
                categories=["Q1", "Q2", "Q3", "Q4"],
                series=[ChartDataSeries(name="2025", values=[12.4, 15.1, 18.7, 22.3])],
            ),
        )],
    ))

    # DIAGRAM (generic)
    slides.append(SlideDefinition(
        slide_type=SlideType.DIAGRAM,
        title="System Architecture",
        body="High-level architecture diagram placeholder for the cloud platform.",
        bullets=["API Gateway", "Service Mesh", "Data Layer", "Observability"],
    ))

    # BLANK
    slides.append(SlideDefinition(
        slide_type=SlideType.BLANK,
        title="Blank Slide",
    ))

    # COMPARISON
    slides.append(SlideDefinition(
        slide_type=SlideType.COMPARISON,
        title="Platform Comparison",
        columns=[
            ColumnContent(title="AWS", bullets=["Broadest service catalog", "Mature ecosystem"]),
            ColumnContent(title="Azure", bullets=["Enterprise integration", "Hybrid cloud strength"]),
        ],
    ))

    # TABLE
    slides.append(SlideDefinition(
        slide_type=SlideType.TABLE,
        title="Migration Timeline",
        elements=[TableElement(
            rows=[
                [TableCell(text="Phase"), TableCell(text="Timeline"), TableCell(text="Status")],
                [TableCell(text="Foundation"), TableCell(text="Q1-Q2"), TableCell(text="Complete")],
                [TableCell(text="Migration"), TableCell(text="Q3-Q4"), TableCell(text="In Progress")],
                [TableCell(text="Optimization"), TableCell(text="Q1 Next Year"), TableCell(text="Planned")],
            ],
            alternate_row_shading=True,
        )],
    ))

    # QUOTE
    slides.append(SlideDefinition(
        slide_type=SlideType.QUOTE,
        title="Leadership Perspective",
        body="The cloud migration has fundamentally transformed how we deliver value to our customers.",
        quote_attribution="Sarah Chen",
        quote_attribution_role="CTO, Meridian Technologies",
    ))

    # BIG_NUMBER
    slides.append(SlideDefinition(
        slide_type=SlideType.BIG_NUMBER,
        title="Cost Savings",
        body="$4.2M",
        subtitle="Annual savings projected by Year 2",
    ))

    # PROCESS
    slides.append(SlideDefinition(
        slide_type=SlideType.PROCESS,
        title="Migration Process",
        steps=[
            ProcessStep(title="Assess", description="Evaluate current workloads", status="completed"),
            ProcessStep(title="Plan", description="Define migration strategy", status="completed"),
            ProcessStep(title="Migrate", description="Move workloads to cloud", status="active"),
            ProcessStep(title="Optimize", description="Fine-tune performance", status="future"),
        ],
        active_step=2,
    ))

    # TIMELINE
    slides.append(SlideDefinition(
        slide_type=SlideType.TIMELINE,
        title="Project Milestones",
        steps=[
            ProcessStep(title="Kickoff", date="Jan 2025", status="completed"),
            ProcessStep(title="Phase 1 Complete", date="Jun 2025", status="completed"),
            ProcessStep(title="Phase 2 Launch", date="Sep 2025", status="active"),
            ProcessStep(title="Full Cutover", date="Mar 2026", status="future"),
        ],
    ))

    # STEP_CARDS
    slides.append(SlideDefinition(
        slide_type=SlideType.STEP_CARDS,
        title="Implementation Steps",
        steps=[
            ProcessStep(title="Discovery", description="Map all services and dependencies"),
            ProcessStep(title="Containerize", description="Package apps in Docker containers"),
            ProcessStep(title="Deploy", description="Roll out to Kubernetes clusters"),
        ],
    ))

    # DASHBOARD
    slides.append(SlideDefinition(
        slide_type=SlideType.DASHBOARD,
        title="Performance Dashboard",
        kpis=[
            KpiCard(value="99.99%", label="Uptime", change="+0.02%", trend="up"),
            KpiCard(value="47ms", label="Avg Latency", change="-12ms", trend="up"),
            KpiCard(value="156", label="Microservices", change="+23", trend="up"),
            KpiCard(value="$4.2M", label="Annual Savings", change="+18%", trend="up"),
        ],
    ))

    # IMAGE_TEXT (no actual image — tests graceful handling)
    slides.append(SlideDefinition(
        slide_type=SlideType.IMAGE_TEXT,
        title="Platform Architecture",
        body="Our cloud-native platform leverages Kubernetes for orchestration with a service mesh for inter-service communication.",
        bullets=["Auto-scaling", "Self-healing", "Observable"],
    ))

    # ICON_GRID
    slides.append(SlideDefinition(
        slide_type=SlideType.ICON_GRID,
        title="Core Capabilities",
        icons=[
            IconItem(icon="⚡", title="Performance", description="Sub-100ms responses"),
            IconItem(icon="🔒", title="Security", description="Zero-trust architecture"),
            IconItem(icon="📊", title="Analytics", description="Real-time dashboards"),
            IconItem(icon="🔄", title="Automation", description="CI/CD pipelines"),
            IconItem(icon="🌐", title="Global", description="Multi-region deployment"),
            IconItem(icon="💰", title="Cost", description="Pay-per-use pricing"),
        ],
    ))

    # CARD_GRID
    slides.append(SlideDefinition(
        slide_type=SlideType.CARD_GRID,
        title="Service Portfolio",
        cards=[
            CardDefinition(title="Compute", icon="⚙", body="Elastic compute with auto-scaling",
                           badge=Badge(text="Core")),
            CardDefinition(title="Storage", icon="💾", body="Object and block storage solutions"),
            CardDefinition(title="Networking", icon="🌐", body="Global load balancing and CDN"),
            CardDefinition(title="Security", icon="🛡", body="IAM, encryption, compliance",
                           badge=Badge(text="Critical", color="#DC3545")),
        ],
    ))

    # TEAM
    slides.append(SlideDefinition(
        slide_type=SlideType.TEAM,
        title="Leadership Team",
        team_members=[
            TeamMember(name="Sarah Chen", role="Chief Technology Officer"),
            TeamMember(name="Marcus Rivera", role="VP Engineering"),
            TeamMember(name="Aisha Patel", role="VP Product"),
            TeamMember(name="David Kim", role="Director of Infrastructure"),
        ],
    ))

    # CLOSING
    slides.append(SlideDefinition(
        slide_type=SlideType.CLOSING,
        title="Thank You",
        subtitle="Questions?",
        cta_text="Schedule a follow-up",
        contact_info=["sarah.chen@meridian.tech", "+1 (555) 123-4567"],
    ))

    # SWOT
    slides.append(SlideDefinition(
        slide_type=SlideType.SWOT,
        title="Strategic SWOT Analysis",
        swot=SwotData(
            strengths=["Strong engineering culture", "Proven cloud expertise", "Customer trust"],
            weaknesses=["Legacy tech debt", "Small DevOps team", "Limited multi-cloud experience"],
            opportunities=["AI/ML integration", "Edge computing", "New market segments"],
            threats=["Competitor cloud offerings", "Regulatory changes", "Talent retention"],
        ),
    ))

    # FUNNEL
    slides.append(SlideDefinition(
        slide_type=SlideType.FUNNEL,
        title="Sales Pipeline",
        funnel_stages=[
            FunnelStage(label="Leads", value="1,200", description="Inbound qualified leads"),
            FunnelStage(label="Qualified", value="480", description="Meeting criteria met"),
            FunnelStage(label="Proposal", value="144", description="Active proposals"),
            FunnelStage(label="Closed Won", value="52", description="Signed contracts"),
        ],
    ))

    # AGENDA
    slides.append(SlideDefinition(
        slide_type=SlideType.AGENDA,
        title="Meeting Agenda",
        agenda_items=[
            AgendaItem(title="Infrastructure Overview", description="Current state review", status="completed"),
            AgendaItem(title="Migration Progress", description="Phase 2 status update", status="active"),
            AgendaItem(title="Budget Review", description="Q4 financial outlook", status="upcoming"),
            AgendaItem(title="Next Steps", description="Action items and timeline", status="upcoming"),
        ],
        active_agenda_item=1,
    ))

    # ORG_CHART
    slides.append(SlideDefinition(
        slide_type=SlideType.ORG_CHART,
        title="Organization Structure",
        org_chart=_build_org_chart(),
    ))

    # MATRIX
    slides.append(SlideDefinition(
        slide_type=SlideType.MATRIX,
        title="Impact-Effort Matrix",
        matrix=_build_matrix(),
    ))

    # PYRAMID
    slides.append(SlideDefinition(
        slide_type=SlideType.PYRAMID,
        title="Strategy Pyramid",
        pyramid_layers=_build_pyramid(),
    ))

    # VENN
    slides.append(SlideDefinition(
        slide_type=SlideType.VENN,
        title="Cross-Functional Alignment",
        venn=_build_venn(),
    ))

    # WATERFALL
    slides.append(SlideDefinition(
        slide_type=SlideType.WATERFALL,
        title="Revenue Bridge Q3 to Q4",
        waterfall_bars=_build_waterfall(),
    ))

    # HUB_SPOKE
    slides.append(SlideDefinition(
        slide_type=SlideType.HUB_SPOKE,
        title="Core Platform Capabilities",
        hub_spoke_center="Core Platform",
        spokes=_build_spokes(),
    ))

    # CYCLE
    slides.append(SlideDefinition(
        slide_type=SlideType.CYCLE,
        title="DevOps Lifecycle",
        cycle_steps=_build_cycle(),
    ))

    # GANTT
    slides.append(SlideDefinition(
        slide_type=SlideType.GANTT,
        title="Project Timeline",
        gantt_tasks=_build_gantt(),
        gantt_phases=["Foundation", "Migration", "Optimization"],
    ))

    defn = PresentationDefinition(metadata=_meta("Kitchen Sink — All 32 Slide Types"), slides=slides)
    path = output_dir / "01_kitchen_sink.pptx"
    gen = DeckGenerator(brand=get_preset("executive"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 02 — All Charts: 12 chart types
# ---------------------------------------------------------------------------

def generate_all_charts(output_dir: Path) -> Path:
    """Generate a deck with all 12 chart types."""
    categories = ["Q1", "Q2", "Q3", "Q4"]
    series_a = ChartDataSeries(name="Revenue", values=[12.4, 15.1, 18.7, 22.3])
    series_b = ChartDataSeries(name="Expenses", values=[8.2, 9.5, 11.0, 13.1])
    basic_data = ChartData(categories=categories, series=[series_a, series_b])

    pie_data = ChartData(
        categories=["Compute", "Storage", "Network", "Security", "Other"],
        series=[ChartDataSeries(name="Spend", values=[35, 25, 20, 12, 8])],
    )

    slides: list[SlideDefinition] = [
        SlideDefinition(slide_type=SlideType.TITLE, title="Chart Type Showcase",
                        subtitle="All 12 chart types"),
    ]

    # Standard chart types with categorical data
    for ct in [ChartType.BAR, ChartType.LINE, ChartType.COLUMN, ChartType.AREA,
               ChartType.STACKED_BAR, ChartType.STACKED_COLUMN]:
        slides.append(SlideDefinition(
            slide_type=SlideType.CHART,
            title=f"{ct.value.replace('_', ' ').title()} Chart",
            elements=[ChartElement(chart_type=ct, data=basic_data)],
        ))

    # Pie and doughnut
    for ct in [ChartType.PIE, ChartType.DOUGHNUT]:
        slides.append(SlideDefinition(
            slide_type=SlideType.CHART,
            title=f"{ct.value.replace('_', ' ').title()} Chart",
            elements=[ChartElement(chart_type=ct, data=pie_data)],
        ))

    # Radar
    slides.append(SlideDefinition(
        slide_type=SlideType.CHART,
        title="Radar Chart",
        elements=[ChartElement(
            chart_type=ChartType.RADAR,
            data=ChartData(
                categories=["Performance", "Security", "Reliability", "Cost", "Scalability"],
                series=[
                    ChartDataSeries(name="Current", values=[6, 7, 8, 5, 6]),
                    ChartDataSeries(name="Target", values=[9, 9, 9, 8, 9]),
                ],
            ),
        )],
    ))

    # Scatter
    slides.append(SlideDefinition(
        slide_type=SlideType.CHART,
        title="Scatter Chart",
        elements=[ChartElement(
            chart_type=ChartType.SCATTER,
            xy_data=XyChartData(series=[
                XyDataSeries(name="Team A", points=[
                    XyDataPoint(x=1, y=3), XyDataPoint(x=2, y=5),
                    XyDataPoint(x=3, y=4), XyDataPoint(x=5, y=8),
                ]),
                XyDataSeries(name="Team B", points=[
                    XyDataPoint(x=1.5, y=2), XyDataPoint(x=3, y=6),
                    XyDataPoint(x=4, y=7), XyDataPoint(x=6, y=9),
                ]),
            ]),
        )],
    ))

    # Bubble
    slides.append(SlideDefinition(
        slide_type=SlideType.CHART,
        title="Bubble Chart",
        elements=[ChartElement(
            chart_type=ChartType.BUBBLE,
            bubble_data=BubbleChartDataModel(series=[
                BubbleDataSeries(name="Products", points=[
                    BubbleDataPoint(x=2, y=6, size=10),
                    BubbleDataPoint(x=5, y=8, size=25),
                    BubbleDataPoint(x=7, y=4, size=15),
                    BubbleDataPoint(x=3, y=9, size=30),
                ]),
            ]),
        )],
    ))

    # Combo
    slides.append(SlideDefinition(
        slide_type=SlideType.CHART,
        title="Combo Chart",
        elements=[ChartElement(
            chart_type=ChartType.COMBO,
            data=basic_data,
            secondary_chart_type=ChartType.LINE,
            secondary_axis=True,
        )],
    ))

    defn = PresentationDefinition(metadata=_meta("Chart Type Showcase"), slides=slides)
    path = output_dir / "02_all_charts.pptx"
    gen = DeckGenerator(brand=get_preset("technical"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 03 — All Diagrams: 8 diagram types
# ---------------------------------------------------------------------------

def _build_org_chart() -> OrgNode:
    return OrgNode(id="ceo", name="Sarah Chen", role="CEO", children=[
        OrgNode(id="vpe", name="Marcus Rivera", role="VP Engineering", children=[
            OrgNode(id="dir_infra", name="David Kim", role="Dir. Infrastructure"),
            OrgNode(id="dir_dev", name="Lisa Wang", role="Dir. Development"),
        ]),
        OrgNode(id="vpp", name="Aisha Patel", role="VP Product", children=[
            OrgNode(id="pm_lead", name="James Taylor", role="Lead PM"),
        ]),
        OrgNode(id="vpd", name="Carlos Ruiz", role="VP Design", children=[
            OrgNode(id="ux_lead", name="Emma Wilson", role="UX Lead"),
        ]),
    ])


def _build_matrix() -> MatrixData:
    return MatrixData(
        x_axis_label="Effort",
        y_axis_label="Impact",
        top_left=MatrixQuadrant(label="Quick Wins", items=["API caching", "Log aggregation"]),
        top_right=MatrixQuadrant(label="Strategic", items=["K8s migration", "Service mesh"]),
        bottom_left=MatrixQuadrant(label="Fill-ins", items=["Docs update", "Monitoring alerts"]),
        bottom_right=MatrixQuadrant(label="Avoid", items=["Full rewrite", "Custom scheduler"]),
    )


def _build_pyramid() -> list[PyramidLayer]:
    return [
        PyramidLayer(label="Vision", description="Cloud-native by 2027"),
        PyramidLayer(label="Strategy", description="Phased migration with zero downtime"),
        PyramidLayer(label="Tactics", description="Container-first, automate everything"),
        PyramidLayer(label="Execution", description="Sprint-based delivery with weekly releases"),
    ]


def _build_venn() -> VennData:
    return VennData(
        circles=[
            VennCircle(label="Engineering", items=["Scalability", "Reliability", "Performance"]),
            VennCircle(label="Product", items=["User needs", "Roadmap", "Metrics"]),
            VennCircle(label="Design", items=["Usability", "Accessibility", "Aesthetics"]),
        ],
        intersection_label="Innovation",
    )


def _build_waterfall() -> list[WaterfallBar]:
    return [
        WaterfallBar(label="Q3 Revenue", value=18.7, bar_type="total"),
        WaterfallBar(label="New Clients", value=2.8, bar_type="increase"),
        WaterfallBar(label="Upsell", value=1.5, bar_type="increase"),
        WaterfallBar(label="Churn", value=-1.2, bar_type="decrease"),
        WaterfallBar(label="Price Adj.", value=0.5, bar_type="increase"),
        WaterfallBar(label="Q4 Revenue", value=22.3, bar_type="total"),
    ]


def _build_spokes() -> list[SpokeItem]:
    return [
        SpokeItem(label="Compute", description="Auto-scaling containers"),
        SpokeItem(label="Storage", description="Distributed object store"),
        SpokeItem(label="Networking", description="Global load balancing"),
        SpokeItem(label="Security", description="Zero-trust architecture"),
        SpokeItem(label="Observability", description="Full-stack monitoring"),
    ]


def _build_cycle() -> list[CycleStep]:
    return [
        CycleStep(label="Plan", description="Define requirements and priorities"),
        CycleStep(label="Code", description="Develop features and fixes"),
        CycleStep(label="Build", description="Compile, test, package"),
        CycleStep(label="Deploy", description="Ship to production"),
        CycleStep(label="Monitor", description="Observe and measure impact"),
    ]


def _build_gantt() -> list[GanttTask]:
    return [
        GanttTask(label="Requirements", start=0.0, duration=0.15, progress=1.0, group="Foundation"),
        GanttTask(label="Architecture", start=0.1, duration=0.2, progress=0.8, group="Foundation"),
        GanttTask(label="Core Services", start=0.25, duration=0.3, progress=0.5, group="Migration"),
        GanttTask(label="Data Migration", start=0.35, duration=0.25, progress=0.3, group="Migration"),
        GanttTask(label="Performance Tuning", start=0.6, duration=0.2, progress=0.0, group="Optimization"),
        GanttTask(label="Cost Optimization", start=0.7, duration=0.25, progress=0.0, group="Optimization"),
    ]


def generate_all_diagrams(output_dir: Path) -> Path:
    """Generate a deck with all 8 diagram types."""
    slides = [
        SlideDefinition(slide_type=SlideType.TITLE, title="Diagram Showcase",
                        subtitle="All 8 diagram types with realistic data"),
        SlideDefinition(slide_type=SlideType.ORG_CHART, title="Organization Structure",
                        org_chart=_build_org_chart()),
        SlideDefinition(slide_type=SlideType.MATRIX, title="Impact-Effort Matrix",
                        matrix=_build_matrix()),
        SlideDefinition(slide_type=SlideType.PYRAMID, title="Strategy Pyramid",
                        pyramid_layers=_build_pyramid()),
        SlideDefinition(slide_type=SlideType.VENN, title="Cross-Functional Alignment",
                        venn=_build_venn()),
        SlideDefinition(slide_type=SlideType.WATERFALL, title="Revenue Bridge Q3 to Q4",
                        waterfall_bars=_build_waterfall()),
        SlideDefinition(slide_type=SlideType.HUB_SPOKE, title="Core Platform Capabilities",
                        hub_spoke_center="Core Platform", spokes=_build_spokes()),
        SlideDefinition(slide_type=SlideType.CYCLE, title="DevOps Lifecycle",
                        cycle_steps=_build_cycle()),
        SlideDefinition(slide_type=SlideType.GANTT, title="Project Timeline",
                        gantt_tasks=_build_gantt(),
                        gantt_phases=["Foundation", "Migration", "Optimization"]),
    ]

    defn = PresentationDefinition(metadata=_meta("Diagram Showcase"), slides=slides)
    path = output_dir / "03_all_diagrams.pptx"
    gen = DeckGenerator(brand=get_preset("consulting"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 04-06 — Archetype decks via planner
# ---------------------------------------------------------------------------

def generate_archetype(
    output_dir: Path,
    filename: str,
    deck_type: str,
    preset: str,
    num_slides: int = 10,
) -> Path:
    """Generate an archetype deck using the SlidePlannerAgent."""
    planner = SlidePlannerAgent()
    defn = planner.run(PlannerInput(
        topic=TOPIC,
        audience=AUDIENCE,
        num_slides=num_slides,
        key_points=KEY_POINTS,
        company=COMPANY,
        deck_type=deck_type,
    ))
    path = output_dir / filename
    gen = DeckGenerator(brand=get_preset(preset))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 07 — Preset Showcase: same 5 slides across 3 presets
# ---------------------------------------------------------------------------

def _showcase_slides() -> list[SlideDefinition]:
    """Build 5 representative slides for preset comparison."""
    return [
        SlideDefinition(
            slide_type=SlideType.TITLE,
            title="Preset Comparison",
            subtitle="Same content, different brand presets",
        ),
        SlideDefinition(
            slide_type=SlideType.CONTENT,
            title="Strategic Priorities",
            bullets=[
                "Accelerate cloud migration across all business units",
                "Reduce infrastructure costs by 42% over 18 months",
                "Achieve 99.99% platform uptime SLA",
                "Build world-class engineering culture",
            ],
        ),
        SlideDefinition(
            slide_type=SlideType.DASHBOARD,
            title="Key Metrics",
            kpis=[
                KpiCard(value="42%", label="Cost Reduction", trend="up"),
                KpiCard(value="99.99%", label="Uptime", trend="up"),
                KpiCard(value="156", label="Services Migrated", trend="up"),
                KpiCard(value="71", label="NPS Score", change="+37", trend="up"),
            ],
        ),
        SlideDefinition(
            slide_type=SlideType.TWO_COLUMN,
            title="Before vs After",
            columns=[
                ColumnContent(title="Before", bullets=["Manual deployments", "3hr recovery time", "$8.4M infra cost"]),
                ColumnContent(title="After", bullets=["Automated CI/CD", "< 5min recovery", "$4.2M infra cost"]),
            ],
        ),
        SlideDefinition(
            slide_type=SlideType.CLOSING,
            title="Next Steps",
            subtitle="Ready to transform your infrastructure",
            cta_text="Schedule a consultation",
        ),
    ]


def generate_preset_showcase(output_dir: Path) -> Path:
    """Generate a deck with the same 5 slides repeated for 3 presets."""
    all_slides: list[SlideDefinition] = []
    for preset_name in ["executive", "startup", "minimal"]:
        # Section divider for each preset
        all_slides.append(SlideDefinition(
            slide_type=SlideType.SECTION,
            title=f"Preset: {preset_name.title()}",
            subtitle=f"Using the {preset_name} brand configuration",
        ))
        all_slides.extend(_showcase_slides())

    # Use executive as the generation brand (sections label the visual intent)
    defn = PresentationDefinition(metadata=_meta("Preset Showcase"), slides=all_slides)
    path = output_dir / "07_preset_showcase.pptx"

    # Generate three separate files instead for true comparison
    for preset_name in ["executive", "startup", "minimal"]:
        preset_path = output_dir / f"07_preset_{preset_name}.pptx"
        preset_defn = PresentationDefinition(
            metadata=_meta(f"Preset Showcase — {preset_name.title()}"),
            slides=_showcase_slides(),
        )
        gen = DeckGenerator(brand=get_preset(preset_name))
        gen.generate(preset_defn, preset_path)

    # Also generate the combined deck
    gen = DeckGenerator(brand=get_preset("executive"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 08 — Designer Features: edge bars, shadows, dividers, auto-fit
# ---------------------------------------------------------------------------

def generate_designer_features(output_dir: Path) -> Path:
    """Generate a deck showcasing designer edge features."""
    slides = [
        SlideDefinition(
            slide_type=SlideType.TITLE,
            title="Designer Feature Showcase",
            subtitle="Edge bars, shadows, dividers, and text auto-fit",
        ),
    ]

    # Content with callout
    slides.append(SlideDefinition(
        slide_type=SlideType.CONTENT,
        title="Slide with Callout Box",
        bullets=["Standard content with a callout box below"],
        callout=CalloutBox(variant="info", title="Note",
                           body="This demonstrates the callout box feature with info styling."),
    ))

    # Dashboard for shadow testing
    slides.append(SlideDefinition(
        slide_type=SlideType.DASHBOARD,
        title="KPI Cards with Shadows",
        kpis=[
            KpiCard(value="42%", label="Cost Reduction", trend="up", badge=Badge(text="On Track")),
            KpiCard(value="156", label="Services", trend="up"),
            KpiCard(value="28", label="Engineers", trend="up"),
        ],
    ))

    # Card grid for edge bar + shadow combo
    slides.append(SlideDefinition(
        slide_type=SlideType.CARD_GRID,
        title="Cards with Edge Styling",
        cards=[
            CardDefinition(title="Compute", icon="⚙", body="Elastic scaling",
                           bullets=["Auto-scaling", "Spot instances"]),
            CardDefinition(title="Storage", icon="💾", body="Durable and fast",
                           badge=Badge(text="New")),
            CardDefinition(title="Network", icon="🌐", body="Global reach"),
        ],
    ))

    # Warning callout
    slides.append(SlideDefinition(
        slide_type=SlideType.CONTENT,
        title="Warning Callout Example",
        bullets=["Production deployment scheduled for Saturday",
                 "All teams must complete testing by Friday EOD"],
        callout=CalloutBox(variant="warning", title="Deployment Window",
                           body="Maintenance window: Saturday 02:00-06:00 UTC. All services will restart."),
    ))

    # Success callout
    slides.append(SlideDefinition(
        slide_type=SlideType.CONTENT,
        title="Success Callout Example",
        bullets=["Phase 2 migration completed ahead of schedule"],
        callout=CalloutBox(variant="success", title="Milestone Achieved",
                           body="All 156 microservices successfully migrated with zero data loss."),
    ))

    # Background gradient
    slides.append(SlideDefinition(
        slide_type=SlideType.SECTION,
        title="Gradient Background",
        subtitle="Testing background gradient rendering",
        background_gradient=["#1B2A4A", "#2D5F8A"],
    ))

    # Title style overrides
    slides.append(SlideDefinition(
        slide_type=SlideType.CONTENT,
        title="Custom Typography",
        title_style=TextStyle(font_size=40, bold=True, color="#6C5CE7"),
        bullets=["This slide uses custom title styling",
                 "Font size 40pt, bold, with purple color"],
    ))

    # Use startup preset for edge bar + shadow features
    defn = PresentationDefinition(metadata=_meta("Designer Feature Showcase"), slides=slides)
    path = output_dir / "08_designer_features.pptx"
    gen = DeckGenerator(brand=get_preset("startup"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 09 — Brand Guide
# ---------------------------------------------------------------------------

def generate_brand_guide_deck(output_dir: Path) -> Path:
    """Generate a 13-slide brand guide using the startup preset."""
    brand = get_preset("startup")
    path = output_dir / "09_brand_guide.pptx"
    generate_brand_guide(brand, path)
    return path


# ---------------------------------------------------------------------------
# 10 — Brand Round-trip: generate → extract → re-generate
# ---------------------------------------------------------------------------

def generate_brand_roundtrip(output_dir: Path) -> Path:
    """Generate a deck, extract its brand, then re-generate with extracted brand."""
    # Step 1: Generate initial deck with consulting preset
    brand_orig = get_preset("consulting")
    initial_slides = [
        SlideDefinition(slide_type=SlideType.TITLE, title="Brand Round-Trip Test",
                        subtitle="Generated with consulting preset"),
        SlideDefinition(slide_type=SlideType.CONTENT, title="Original Content",
                        bullets=["This deck was generated with the consulting brand preset",
                                 "It will be analyzed and re-generated"]),
        SlideDefinition(slide_type=SlideType.DASHBOARD, title="Metrics",
                        kpis=[
                            KpiCard(value="42%", label="Savings", trend="up"),
                            KpiCard(value="99.99%", label="Uptime", trend="up"),
                        ]),
    ]
    initial_defn = PresentationDefinition(metadata=_meta("Brand Round-Trip — Original"), slides=initial_slides)
    initial_path = output_dir / "10_brand_roundtrip_original.pptx"
    gen = DeckGenerator(brand=brand_orig)
    gen.generate(initial_defn, initial_path)

    # Step 2: Extract brand from the generated file
    extracted_brand = extract_brand(initial_path)

    # Step 3: Re-generate with extracted brand
    roundtrip_slides = [
        SlideDefinition(slide_type=SlideType.TITLE, title="Brand Round-Trip Result",
                        subtitle="Re-generated with extracted brand"),
        SlideDefinition(slide_type=SlideType.CONTENT, title="Extracted Brand Applied",
                        bullets=["This deck uses the brand extracted from the original",
                                 f"Primary color: {extracted_brand.colors.primary}",
                                 f"Heading font: {extracted_brand.fonts.heading_font}"]),
        SlideDefinition(slide_type=SlideType.DASHBOARD, title="Same Metrics, New Brand",
                        kpis=[
                            KpiCard(value="42%", label="Savings", trend="up"),
                            KpiCard(value="99.99%", label="Uptime", trend="up"),
                        ]),
    ]
    roundtrip_defn = PresentationDefinition(
        metadata=_meta("Brand Round-Trip — Extracted"), slides=roundtrip_slides)
    path = output_dir / "10_brand_roundtrip.pptx"
    gen2 = DeckGenerator(brand=extracted_brand)
    gen2.generate(roundtrip_defn, path)
    return path


# ---------------------------------------------------------------------------
# 11 — Markdown Spec
# ---------------------------------------------------------------------------

MARKDOWN_SPEC = """\
# Cloud Infrastructure Modernization

## Slide 1: Title Slide
Cloud Infrastructure Modernization
A Strategic Roadmap for Enterprise Transformation

## Slide 2: Executive Summary
- 42% reduction in infrastructure costs over 18 months
- Migration of 156 microservices to Kubernetes
- 99.99% uptime SLA achieved in Q3
- $4.2M annual savings projected by Year 2

## Slide 3: Current vs Future Architecture
- Monolithic applications to microservices
- Manual deployment to automated CI/CD
- Single-region to multi-region deployment
- 3hr recovery time to under 5 minutes
- $8.4M infra cost reduced to $4.2M
- On-prem servers migrated to cloud-native
- Waterfall releases to weekly deployments

## Slide 4: Key Metrics Dashboard
42% cost reduction achieved
99.99% uptime SLA exceeded
156 microservices migrated to date
$4.2M annual savings projected

## Slide 5: Implementation Roadmap
- Phase 1: Foundation and containerization
- Phase 2: Service migration and testing
- Phase 3: Performance optimization
- Phase 4: Cost optimization and scaling

## Slide 6: Thank You
Ready to transform your infrastructure
"""


def generate_from_markdown(output_dir: Path) -> Path:
    """Generate a deck from a markdown spec string."""
    defn, brand = parse_spec(MARKDOWN_SPEC)
    path = output_dir / "11_markdown_spec.pptx"
    gen = DeckGenerator(brand=brand or get_preset("executive"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# 12 — Large Deck: 20 slides via planner
# ---------------------------------------------------------------------------

def generate_large_deck(output_dir: Path) -> Path:
    """Generate a 20-slide deck to test scaling."""
    planner = SlidePlannerAgent()
    defn = planner.run(PlannerInput(
        topic=TOPIC,
        audience=AUDIENCE,
        num_slides=20,
        key_points=KEY_POINTS,
        company=COMPANY,
        deck_type="strategy_deck",
    ))
    path = output_dir / "12_large_deck.pptx"
    gen = DeckGenerator(brand=get_preset("consulting"))
    gen.generate(defn, path)
    return path


# ---------------------------------------------------------------------------
# Review all generated decks
# ---------------------------------------------------------------------------

def review_all(output_dir: Path) -> dict:
    """Review every generated PPTX and write a summary JSON."""
    engine = ReviewEngine()
    results = {}
    for pptx_file in sorted(output_dir.glob("*.pptx")):
        try:
            review = engine.review_file(pptx_file)
            error_count = sum(1 for i in review.issues if i.severity.value == "error")
            warning_count = sum(1 for i in review.issues if i.severity.value == "warning")
            results[pptx_file.name] = {
                "score": review.overall_score,
                "issues": review.total_issues,
                "errors": error_count,
                "warnings": warning_count,
            }
        except Exception as e:
            results[pptx_file.name] = {"score": 0, "issues": -1, "error": str(e)}

    review_path = output_dir / "review_results.json"
    review_path.write_text(json.dumps(results, indent=2))
    return results


# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------

def main() -> None:
    output_dir = PROJECT_ROOT / "test_output"
    output_dir.mkdir(exist_ok=True)

    generators = [
        ("01 Kitchen Sink (32 types)", lambda: generate_kitchen_sink(output_dir)),
        ("02 All Charts (12 types)", lambda: generate_all_charts(output_dir)),
        ("03 All Diagrams (8 types)", lambda: generate_all_diagrams(output_dir)),
        ("04 Pitch Deck (startup)", lambda: generate_archetype(output_dir, "04_pitch_deck.pptx", "pitch_deck", "startup")),
        ("05 Board Deck (executive)", lambda: generate_archetype(output_dir, "05_board_deck.pptx", "board_deck", "executive")),
        ("06 Consulting Deck (consulting)", lambda: generate_archetype(output_dir, "06_consulting_deck.pptx", "strategy_deck", "consulting")),
        ("07 Preset Showcase", lambda: generate_preset_showcase(output_dir)),
        ("08 Designer Features", lambda: generate_designer_features(output_dir)),
        ("09 Brand Guide", lambda: generate_brand_guide_deck(output_dir)),
        ("10 Brand Round-trip", lambda: generate_brand_roundtrip(output_dir)),
        ("11 Markdown Spec", lambda: generate_from_markdown(output_dir)),
        ("12 Large Deck (20 slides)", lambda: generate_large_deck(output_dir)),
    ]

    print(f"Generating test decks into {output_dir}/\n")
    t0 = time.time()

    for label, gen_fn in generators:
        try:
            t1 = time.time()
            path = gen_fn()
            elapsed = time.time() - t1
            print(f"  [OK]  {label:<40} -> {path.name}  ({elapsed:.1f}s)")
        except Exception as e:
            print(f"  [ERR] {label:<40} -> {e}")

    # Review all generated decks
    print("\nReviewing all generated decks...")
    results = review_all(output_dir)
    total_elapsed = time.time() - t0

    print(f"\n{'='*60}")
    print(f"{'File':<40} {'Score':>6} {'Issues':>7} {'Errors':>7}")
    print(f"{'-'*60}")
    for fname, data in results.items():
        score = f"{data['score']:.1f}" if data.get("score", 0) > 0 else "ERR"
        issues = str(data.get("issues", "?"))
        errors = str(data.get("errors", "?"))
        print(f"  {fname:<38} {score:>6} {issues:>7} {errors:>7}")
    print(f"{'='*60}")
    print(f"\nTotal time: {total_elapsed:.1f}s")
    print(f"Review results: {output_dir / 'review_results.json'}")


if __name__ == "__main__":
    main()
