"""
CLI help content for DAZZLE MCP server.

Provides structured documentation for CLI commands to help LLM agents
understand how to use the dazzle tool effectively.

Command data is auto-generated by introspecting the typer app tree so it
stays complete and never goes stale.  Three small curated dicts supply
metadata that introspection cannot derive (categories, MCP equivalents,
and hand-written enrichments like output URLs and prerequisite lists).
"""

from __future__ import annotations

import inspect
from typing import Any

# =============================================================================
# Curated metadata (introspection cannot derive these)
# =============================================================================

CATEGORY_MAP: dict[str, str] = {
    # --- sub-app names → display category ---
    "auth": "Authentication",
    "composition": "Visual Composition",
    "db": "Database",
    "deploy": "Deploy",
    "discovery": "Discovery",
    "dlq": "Events",
    "e2e": "E2E Testing",
    "events": "Events",
    "kg": "Knowledge Graph",
    "lsp": "Language Server",
    "mcp": "MCP Server",
    "outbox": "Events",
    "pipeline": "Pipeline",
    "pitch": "Pitch Deck",
    "process-migrate": "Process Migration",
    "specs": "API Specs",
    "story": "Stories",
    "stubs": "Stubs",
    "test": "Testing",
    "vocab": "Vocabulary",
    # --- top-level command names → display category ---
    "serve": "Runtime",
    "build": "Code Generation",
    "build-ui": "Code Generation",
    "build-api": "Code Generation",
    "info": "Runtime",
    "stop": "Runtime",
    "rebuild": "Runtime",
    "logs": "Runtime",
    "status": "Runtime",
    "migrate": "Runtime",
    "schema": "Runtime",
    "check": "Runtime",
    "init": "Project",
    "validate": "Validation",
    "lint": "Validation",
    "inspect": "Validation",
    "layout-plan": "Validation",
    "analyze-spec": "Validation",
    "example": "Project",
    "doctor": "Project",
    "workshop": "Project",
    "grammar": "Validation",
}

MCP_TOOL_MAP: dict[str, str] = {
    "validate": "dsl(operation='validate')",
    "lint": "dsl(operation='lint')",
    "inspect": "dsl(operation='inspect_entity')",
    "analyze-spec": "spec_analyze(operation='discover_entities')",
    "pipeline run": "pipeline(operation='run')",
    "composition audit": "composition(operation='audit')",
    "composition report": "composition(operation='report')",
    "discovery coherence": "discovery(operation='coherence')",
    "story propose": "story(operation='propose')",
    "story list": "story(operation='get')",
    "story generate-tests": "story(operation='generate_tests')",
    "test generate": "dsl_test(operation='generate')",
    "test dsl-run": "dsl_test(operation='run')",
    "test dsl-coverage": "dsl_test(operation='coverage')",
    "test run-all": "dsl_test(operation='run_all')",
    "test diff-personas": "dsl_test(operation='diff_personas')",
    "specs openapi": "dsl(operation='export_frontend_spec')",
    "pitch scaffold": "pitch(operation='scaffold')",
    "pitch generate": "pitch(operation='generate')",
    "pitch validate": "pitch(operation='validate')",
    "kg export": "graph(operation='export')",
    "kg import": "graph(operation='import')",
    "e2e run": "e2e_test(operation='run')",
    "e2e run-all": "e2e_test(operation='run')",
}

ENRICHMENTS: dict[str, dict[str, Any]] = {
    "serve": {
        "output": {
            "ui_url": "http://localhost:3000",
            "api_url": "http://localhost:8000",
            "docs_url": "http://localhost:8000/docs",
        },
        "notes": [
            "Dazzle is the recommended runtime - no code generation needed",
            "Use --test-mode for E2E testing with Playwright",
            "Use --local for development without Docker",
        ],
    },
    "init": {
        "creates": [
            "dazzle.toml - Project manifest",
            "dsl/ - DSL source directory",
            "dsl/app.dsl - Starter DSL file",
            "README.md - Getting started guide",
        ],
    },
    "lint": {
        "checks": [
            "Naming conventions",
            "Dead modules",
            "Unused imports",
            "Style violations",
        ],
    },
    "test run": {
        "prerequisites": [
            "App running with: dazzle serve --test-mode",
            "Playwright installed: pip install playwright && playwright install chromium",
        ],
    },
    "stubs list": {
        "output": {
            "service_name": "Name of the domain service",
            "kind": "Service kind (domain_logic, validation, integration, workflow)",
            "stub_language": "Target language (python, typescript)",
            "status": "implemented | not_implemented | missing",
        },
    },
    "test generate": {
        "generates": [
            "CRUD flows for each entity",
            "Validation flows for field constraints",
            "Navigation flows for surfaces",
            "Auth flows (if auth enabled)",
            "Test fixtures with sample data",
        ],
    },
    "build": {
        "notes": [
            "Dazzle runtime is preferred for development",
            "Code generation is for custom deployments",
        ],
    },
}


# =============================================================================
# Introspection engine
# =============================================================================


def _extract_options(callback: Any) -> dict[str, str]:
    """Extract option flags and help text from a typer callback's signature."""
    try:
        from typer.models import ArgumentInfo, OptionInfo
    except ImportError:
        return {}

    options: dict[str, str] = {}

    try:
        sig = inspect.signature(callback)
    except (ValueError, TypeError):
        return {}

    for param_name, param in sig.parameters.items():
        default = param.default
        if isinstance(default, OptionInfo):
            decls = default.param_decls
            if decls:
                flags = ", ".join(decls)
            else:
                flags = f"--{param_name.replace('_', '-')}"
            help_text = default.help or ""
            options[flags] = help_text
        elif isinstance(default, ArgumentInfo):
            help_text = default.help or ""
            options[f"<{param_name.upper()}>"] = help_text

    return options


def _extract_examples_from_docstring(docstring: str) -> list[str]:
    """Parse an ``Examples:`` block from a docstring."""
    if not docstring:
        return []

    examples: list[str] = []
    in_examples = False

    for line in docstring.split("\n"):
        stripped = line.strip()
        if stripped.lower().startswith("example"):
            in_examples = True
            continue
        if in_examples:
            if stripped.startswith("dazzle "):
                # Strip inline comments for cleaner display
                examples.append(stripped)
            elif stripped == "" or stripped.startswith("#"):
                continue
            elif examples:
                # Non-empty, non-example, non-comment line → end of block
                break

    return examples


def _extract_command_info(full_name: str, callback: Any, prefix: str) -> dict[str, Any]:
    """Build one command entry from a typer callback function."""
    # Determine category — look up by sub-app prefix, then by full name
    group = prefix.split()[0] if prefix else full_name
    category = CATEGORY_MAP.get(group, CATEGORY_MAP.get(full_name, "Other"))

    # Description: first paragraph of cleaned docstring, collapsed to one line
    doc = inspect.getdoc(callback) or ""
    description = doc.split("\n\n")[0].strip() if doc else ""
    description = " ".join(description.split())

    # Options
    options = _extract_options(callback)

    # Syntax
    syntax = f"dazzle {full_name}"
    if options:
        syntax += " [OPTIONS]"

    # Examples parsed from docstring
    examples = _extract_examples_from_docstring(doc)

    # MCP tool equivalent
    mcp_tool = MCP_TOOL_MAP.get(full_name)

    entry: dict[str, Any] = {
        "category": category,
        "description": description,
        "syntax": syntax,
    }

    if options:
        entry["options"] = options
    if examples:
        entry["examples"] = examples
    if mcp_tool:
        entry["mcp_tool"] = mcp_tool

    # Merge curated enrichments
    if full_name in ENRICHMENTS:
        entry.update(ENRICHMENTS[full_name])

    return entry


def _walk_typer_group(
    typer_instance: Any, prefix: str, commands: dict[str, dict[str, Any]]
) -> None:
    """Recursively walk a Typer app's commands and nested groups."""
    for cmd_info in typer_instance.registered_commands:
        name = cmd_info.name
        callback = cmd_info.callback
        if name and callback:
            full_name = f"{prefix} {name}" if prefix else name
            commands[full_name] = _extract_command_info(full_name, callback, prefix)

    for group_info in typer_instance.registered_groups:
        group_name = group_info.name
        sub_app = group_info.typer_instance
        if group_name and sub_app:
            nested_prefix = f"{prefix} {group_name}" if prefix else group_name
            _walk_typer_group(sub_app, nested_prefix, commands)


def _introspect_typer_app() -> dict[str, dict[str, Any]]:
    """Import the typer app and introspect its entire command tree."""
    from dazzle.cli import app

    commands: dict[str, dict[str, Any]] = {}
    _walk_typer_group(app, "", commands)
    return commands


# =============================================================================
# Cache
# =============================================================================

_cached_commands: dict[str, dict[str, Any]] | None = None


def _get_commands() -> dict[str, dict[str, Any]]:
    """Return the introspected command dict, building it once on first call."""
    global _cached_commands
    if _cached_commands is None:
        _cached_commands = _introspect_typer_app()
    return _cached_commands


# =============================================================================
# Quick Reference (curated — not introspectable)
# =============================================================================

QUICK_REFERENCE = """
# DAZZLE CLI Quick Reference

## Run an App (Primary Workflow)
```bash
cd my-project
dazzle serve           # Start the app
# UI: http://localhost:3000
# API: http://localhost:8000/docs
```

## Create a New Project
```bash
dazzle init my-app         # Create new project
dazzle init --from simple_task  # Copy from example
```

## Validate & Inspect
```bash
dazzle validate            # Check DSL syntax
dazzle lint                # Extended checks
dazzle layout-plan         # Visualize workspaces
```

## E2E Testing
```bash
dazzle serve --test-mode  # Start with test endpoints
dazzle test generate -o tests.json
dazzle test run
```

## Common Issues

### "No dazzle.toml found"
Run commands from project root (directory containing dazzle.toml)

### Port already in use
```bash
dazzle stop            # Stop existing container
dazzle serve -p 4000   # Use different port
```

### Docker issues
```bash
dazzle serve --local   # Run without Docker
```
"""


# =============================================================================
# Lookup Functions
# =============================================================================


def get_cli_help(command: str | None = None) -> dict[str, Any]:
    """
    Get CLI help for a specific command or general overview.

    Args:
        command: Command name (e.g., 'serve', 'test run') or None for overview

    Returns:
        Help information for the command
    """
    cli_commands = _get_commands()

    if command is None:
        # Return overview
        categories: dict[str, list[str]] = {}
        for cmd, info in cli_commands.items():
            cat = info.get("category", "Other")
            if cat not in categories:
                categories[cat] = []
            categories[cat].append(cmd)

        return {
            "overview": True,
            "quick_reference": QUICK_REFERENCE,
            "categories": categories,
            "primary_command": "dazzle serve",
            "hint": "Use get_cli_help with a specific command for detailed help",
        }

    # Normalize command
    cmd_normalized = command.lower().strip()

    # Direct lookup
    if cmd_normalized in cli_commands:
        return {"command": cmd_normalized, "found": True, **cli_commands[cmd_normalized]}

    # Try with 'dazzle' prefix removed
    if cmd_normalized.startswith("dazzle "):
        cmd_normalized = cmd_normalized[7:]
        if cmd_normalized in cli_commands:
            return {
                "command": cmd_normalized,
                "found": True,
                **cli_commands[cmd_normalized],
            }

    # Partial match
    matches = [cmd for cmd in cli_commands if cmd_normalized in cmd or cmd in cmd_normalized]
    if matches:
        return {
            "command": command,
            "found": False,
            "suggestions": matches,
            "hint": f"Did you mean one of: {', '.join(matches)}?",
        }

    return {
        "command": command,
        "found": False,
        "error": f"Command '{command}' not found",
        "available_commands": list(cli_commands.keys()),
    }


def get_workflow_guide(workflow: str) -> dict[str, Any]:
    """
    Get a step-by-step guide for common workflows.

    Args:
        workflow: Workflow name (e.g., 'new_project', 'add_entity', 'setup_testing')

    Returns:
        Step-by-step workflow guide
    """
    workflows: dict[str, dict[str, Any]] = {
        "getting_started": {
            "name": "Getting Started with DAZZLE",
            "description": "Complete beginner's guide to building your first DAZZLE app",
            "steps": [
                {
                    "step": 1,
                    "action": "Create a new project",
                    "command": "dazzle init my-app && cd my-app",
                    "notes": "This creates dazzle.toml and dsl/app.dsl starter files",
                },
                {
                    "step": 2,
                    "action": "Understand the project structure",
                    "explanation": """
my-app/
\u251c\u2500\u2500 dazzle.toml    # Project manifest (name, version)
\u251c\u2500\u2500 dsl/
\u2502   \u2514\u2500\u2500 app.dsl    # Your DSL definitions
\u2514\u2500\u2500 .dazzle/       # Runtime data (created on first run)
    \u2514\u2500\u2500 data.db    # SQLite database""",
                },
                {
                    "step": 3,
                    "action": "Edit the DSL file",
                    "file": "dsl/app.dsl",
                    "example": """module my_app
app MyApp "My Application"

# Define your data model
entity Task "Task":
  id: uuid pk
  title: str(200) required
  completed: bool=false
  created_at: datetime auto_add

# Define the UI
surface task_list "Tasks":
  uses entity Task
  mode: list
  section main:
    field title "Title"
    field completed "Done"
  ux:
    purpose: "Track your daily tasks"
    sort: created_at desc
    empty: "No tasks yet. Create your first one!"

surface task_create "New Task":
  uses entity Task
  mode: create
  section main:
    field title "Title" """,
                },
                {
                    "step": 4,
                    "action": "Validate your DSL",
                    "command": "dazzle validate",
                    "notes": "Fix any syntax errors before running",
                },
                {
                    "step": 5,
                    "action": "Run the application",
                    "command": "dazzle serve",
                    "output": {
                        "ui": "http://localhost:3000",
                        "api": "http://localhost:8000/docs",
                    },
                    "notes": "Dazzle creates the database and runs both frontend and API",
                },
            ],
            "next_steps": [
                "Add more entities (use 'add_entity' workflow)",
                "Create a dashboard workspace (use 'add_workspace' workflow)",
                "Add personas for role-based access (use 'add_personas' workflow)",
                "Generate demo data: mcp__dazzle__propose_demo_blueprint",
                "Set up E2E testing (use 'setup_testing' workflow)",
            ],
            "demo_data_hint": """
After validation succeeds, generate realistic demo data:

1. Propose a demo data blueprint:
   mcp__dazzle__propose_demo_blueprint

2. Review and save the blueprint:
   mcp__dazzle__save_demo_blueprint

3. Generate demo data files:
   mcp__dazzle__generate_demo_data
""",
        },
        "new_project": {
            "name": "Create a New DAZZLE Project",
            "steps": [
                {
                    "step": 1,
                    "action": "Initialize project",
                    "command": "dazzle init my-app",
                    "notes": "Or use --from simple_task to copy an example",
                },
                {
                    "step": 2,
                    "action": "Navigate to project",
                    "command": "cd my-app",
                },
                {
                    "step": 3,
                    "action": "Edit DSL",
                    "file": "dsl/app.dsl",
                    "notes": "Define your entities, surfaces, and workspaces",
                },
                {
                    "step": 4,
                    "action": "Validate",
                    "command": "dazzle validate",
                },
                {
                    "step": 5,
                    "action": "Run the app",
                    "command": "dazzle serve",
                },
            ],
        },
        "add_entity": {
            "name": "Add a New Entity",
            "steps": [
                {
                    "step": 1,
                    "action": "Edit DSL file",
                    "file": "dsl/app.dsl",
                    "example": """entity Customer "Customer":
  id: uuid pk
  name: str(200) required
  email: email unique
  created_at: datetime auto_add""",
                },
                {
                    "step": 2,
                    "action": "Add CRUD surfaces",
                    "example": """surface customer_list "Customers":
  uses entity Customer
  mode: list
  section main:
    field name
    field email

surface customer_create "New Customer":
  uses entity Customer
  mode: create""",
                },
                {
                    "step": 3,
                    "action": "Validate",
                    "command": "dazzle validate",
                },
                {
                    "step": 4,
                    "action": "Restart app",
                    "command": "dazzle serve",
                    "notes": "Dazzle picks up changes automatically on restart",
                },
            ],
        },
        "setup_testing": {
            "name": "Set Up E2E Testing",
            "steps": [
                {
                    "step": 1,
                    "action": "Install Playwright",
                    "command": "pip install playwright && playwright install chromium",
                },
                {
                    "step": 2,
                    "action": "Start app in test mode",
                    "command": "dazzle serve --test-mode",
                    "notes": "Enables /__test__/* endpoints for fixtures",
                },
                {
                    "step": 3,
                    "action": "Generate test spec",
                    "command": "dazzle test generate -o testspec.json",
                },
                {
                    "step": 4,
                    "action": "Run tests",
                    "command": "dazzle test run -v",
                },
            ],
        },
        "add_workspace": {
            "name": "Add a Dashboard Workspace",
            "description": "Create a workspace that aggregates multiple data views",
            "steps": [
                {
                    "step": 1,
                    "action": "Add workspace to DSL",
                    "file": "dsl/app.dsl",
                    "example": """workspace dashboard "Dashboard":
  purpose: "Overview of all active tasks and team metrics"

  # Recent urgent tasks
  urgent_tasks:
    source: Task
    filter: priority = high and status != done
    sort: due_date asc
    limit: 5
    action: task_edit
    empty: "No urgent tasks!"

  # Activity summary
  recent_activity:
    source: Task
    filter: status = done
    sort: completed_at desc
    limit: 10
    display: timeline

  # Key metrics
  metrics:
    aggregate:
      total_tasks: count(Task)
      completed: count(Task where status = done)
      overdue: count(Task where due_date < today and status != done)""",
                },
                {
                    "step": 2,
                    "action": "Validate",
                    "command": "dazzle validate",
                },
                {
                    "step": 3,
                    "action": "Preview layout",
                    "command": "dazzle layout-plan --explain",
                    "notes": "See which archetype is selected and why",
                },
            ],
            "archetypes": [
                "FOCUS_METRIC - Single KPI with supporting data",
                "SCANNER_TABLE - Data table for scanning records",
                "DUAL_PANE_FLOW - List + detail side by side",
                "MONITOR_WALL - Multiple signal regions",
                "COMMAND_CENTER - Complex multi-region layout",
            ],
            "next_steps": [
                "Define personas for role-based access (use 'add_personas' workflow)",
                "Add attention signals to highlight important data",
                "Generate demo data: mcp__dazzle__propose_demo_blueprint",
            ],
            "persona_hint": """
You've created a workspace. Consider defining personas for role-based access:

  workspace dashboard \u2192 persona admin (full visibility)
  workspace customer_portal \u2192 persona customer (sees own data)
  workspace sales_dashboard \u2192 persona sales_rep (sees team data)

Use: get_workflow_guide('add_personas') for step-by-step instructions.
""",
        },
        "add_personas": {
            "name": "Add Role-Based Access with Personas",
            "description": "Define different views for admin, manager, and regular users",
            "steps": [
                {
                    "step": 1,
                    "action": "Add personas to surface UX block",
                    "file": "dsl/app.dsl",
                    "example": """surface user_list "Users":
  uses entity User
  mode: list

  section main:
    field name
    field email
    field role

  ux:
    purpose: "Manage user accounts"

    # Admin sees everything
    for admin:
      scope: all
      action_primary: user_create
      show_aggregate: total_users, active_count

    # Manager sees their department
    for manager:
      scope: department = current_user.department
      hide: salary, ssn
      action_primary: user_invite

    # Regular users see only themselves
    for member:
      scope: id = current_user.id
      read_only: true""",
                },
                {
                    "step": 2,
                    "action": "Add personas to workspace",
                    "example": """workspace dashboard "Dashboard":
  purpose: "Team overview"

  tasks:
    source: Task

  ux:
    for admin:
      scope: all
      purpose: "Full system visibility"

    for member:
      scope: assigned_to = current_user
      purpose: "Your personal tasks" """,
                },
            ],
            "persona_directives": {
                "scope": "Filter expression (all, owner = current_user, etc.)",
                "purpose": "Persona-specific purpose statement",
                "show": "Fields to display",
                "hide": "Fields to hide",
                "show_aggregate": "Metrics to display",
                "action_primary": "Default action surface",
                "read_only": "Disable editing (true/false)",
            },
        },
        "add_relationships": {
            "name": "Add Entity Relationships",
            "description": "Connect entities with foreign key references",
            "steps": [
                {
                    "step": 1,
                    "action": "Define related entities",
                    "example": """entity Project "Project":
  id: uuid pk
  name: str(200) required
  owner: ref User required

entity Task "Task":
  id: uuid pk
  title: str(200) required
  project: ref Project required
  assigned_to: ref User optional""",
                },
                {
                    "step": 2,
                    "action": "Show related data in surfaces",
                    "example": """surface task_list "Tasks":
  uses entity Task
  mode: list

  section main:
    field title
    field project.name "Project"
    field assigned_to.name "Assigned To" """,
                },
            ],
            "relationship_types": {
                "ref Entity required": "Must have a related record",
                "ref Entity optional": "Can be null",
                "ref Entity[]": "One-to-many (array of references)",
            },
        },
        "add_attention_signals": {
            "name": "Add Attention Signals",
            "description": "Alert users to important conditions in their data",
            "steps": [
                {
                    "step": 1,
                    "action": "Add attention blocks to surface UX",
                    "example": """surface task_list "Tasks":
  uses entity Task
  mode: list

  section main:
    field title
    field status
    field due_date

  ux:
    purpose: "Track task progress"

    # Critical - action required immediately
    attention critical:
      when: due_date < today and status != done
      message: "Overdue!"
      action: task_edit

    # Warning - needs attention soon
    attention warning:
      when: due_date = today and status != done
      message: "Due today"

    # Notice - informational
    attention notice:
      when: status = blocked
      message: "Blocked - needs help" """,
                },
            ],
            "levels": {
                "critical": "Requires immediate action (red)",
                "warning": "Needs attention soon (yellow/orange)",
                "notice": "Worth noting (blue)",
                "info": "Informational only (gray)",
            },
        },
        "add_domain_service": {
            "name": "Add a Domain Service",
            "description": "Create custom business logic with DSL declaration and Python stub",
            "steps": [
                {
                    "step": 1,
                    "action": "Add service declaration to DSL",
                    "file": "dsl/app.dsl",
                    "example": """service calculate_discount "Calculate Order Discount":
  kind: domain_logic
  input:
    order_id: uuid required
    coupon_code: str(20)
  output:
    discount_amount: decimal(10,2)
    discount_type: str(20)
    applied_rules: json
  guarantees:
    - "Must not modify order record"
    - "Must validate coupon exists before applying"
  stub: python""",
                },
                {
                    "step": 2,
                    "action": "Validate DSL",
                    "command": "dazzle validate",
                    "notes": "Ensure service declaration is syntactically correct",
                },
                {
                    "step": 3,
                    "action": "Generate stub file",
                    "command": "dazzle stubs generate --service calculate_discount",
                    "creates": "stubs/calculate_discount.py",
                },
                {
                    "step": 4,
                    "action": "Implement the stub",
                    "file": "stubs/calculate_discount.py",
                    "example": """def calculate_discount(order_id: str, coupon_code: str | None = None) -> CalculateDiscountResult:
    order = db.get_order(order_id)

    # Check for valid coupon
    if coupon_code:
        coupon = db.get_coupon(coupon_code)
        if coupon and coupon.is_valid:
            return {
                "discount_amount": order.total * coupon.discount_percent,
                "discount_type": "coupon",
                "applied_rules": {"coupon": coupon_code, "percent": coupon.discount_percent}
            }

    # Apply default volume discount
    if order.total >= 100:
        return {
            "discount_amount": order.total * 0.10,
            "discount_type": "volume",
            "applied_rules": {"rule": "10% off orders over $100"}
        }

    return {"discount_amount": 0, "discount_type": "none", "applied_rules": {}}""",
                },
                {
                    "step": 5,
                    "action": "Restart app",
                    "command": "dazzle serve",
                    "notes": "Dazzle discovers and loads stubs automatically",
                },
            ],
            "service_kinds": {
                "domain_logic": "Business calculations (tax, pricing, scoring)",
                "validation": "Complex validation across fields/entities",
                "integration": "External API calls (payment, email, SMS)",
                "workflow": "Multi-step processes (approvals, fulfillment)",
            },
        },
        "pitch_deck": {
            "name": "Create Pitch Deck",
            "description": "Generate an investor pitch deck from your DSL project",
            "steps": [
                {
                    "step": 1,
                    "action": "Scaffold pitchspec",
                    "command": "pitch(operation='scaffold')",
                    "notes": "Creates pitchspec.yaml with template sections",
                },
                {
                    "step": 2,
                    "action": "Fill in company details",
                    "file": "pitchspec.yaml",
                    "notes": "Add company name, tagline, funding_ask, problem, solution, market sizing, team, and financials",
                },
                {
                    "step": 3,
                    "action": "Validate the pitchspec",
                    "command": "pitch(operation='validate')",
                    "notes": "Checks for structural errors and missing required fields",
                },
                {
                    "step": 4,
                    "action": "Generate the deck",
                    "command": "pitch(operation='generate', format='all')",
                    "notes": "Creates pitch_deck.pptx and pitch_narrative.md",
                },
                {
                    "step": 5,
                    "action": "Review content quality",
                    "command": "pitch(operation='review')",
                    "notes": "Analyzes each section for investor-readiness and gives specific improvement suggestions",
                },
                {
                    "step": 6,
                    "action": "Iterate on content",
                    "notes": "Address review suggestions, then re-run validate \u2192 generate \u2192 review until satisfied",
                },
            ],
            "next_steps": [
                "Use pitch(operation='get') to inspect current pitchspec contents",
                "Use pitch(operation='review') after each edit cycle to track improvement",
                "Add speaker_notes to sections for presenter guidance",
                "Add extra_slides for appendix material (case studies, technical architecture)",
            ],
        },
        "run_discovery": {
            "name": "Run Capability Discovery",
            "description": "Find gaps between DSL spec and running app using agent-driven discovery",
            "steps": [
                {
                    "step": 1,
                    "action": "Start app in test mode",
                    "command": "dazzle serve --test-mode",
                    "notes": "The app must be running for discovery to explore it",
                },
                {
                    "step": 2,
                    "action": "Check readiness",
                    "mcp_tool": "discovery(operation='status')",
                    "notes": "Verifies app is reachable and DSL is valid",
                },
                {
                    "step": 3,
                    "action": "Run entity completeness analysis",
                    "mcp_tool": "discovery(operation='run', mode='entity_completeness')",
                    "notes": "Statically checks CRUD coverage for each entity and state machine transition UI",
                },
                {
                    "step": 4,
                    "action": "Run workflow coherence analysis",
                    "mcp_tool": "discovery(operation='run', mode='workflow_coherence')",
                    "notes": "Checks process/story integrity: human_task surfaces, subprocess refs, trigger validity",
                },
                {
                    "step": 5,
                    "action": "Optionally run persona walkthrough",
                    "mcp_tool": "discovery(operation='run', mode='persona')",
                    "notes": "Open-ended exploration as a persona (requires LLM, costs tokens)",
                },
                {
                    "step": 6,
                    "action": "Compile findings into proposals",
                    "mcp_tool": "discovery(operation='compile')",
                    "notes": "Groups observations by root cause, generates narratives, prioritizes by severity",
                },
                {
                    "step": 7,
                    "action": "Generate DSL patches",
                    "mcp_tool": "discovery(operation='emit')",
                    "notes": "Produces validated DSL fragments to fix discovered gaps",
                },
            ],
            "modes": {
                "entity_completeness": "Static CRUD coverage + state machine UI analysis (fast, no browser needed)",
                "workflow_coherence": "Static process/story integrity analysis (fast, no browser needed)",
                "persona": "Open-ended persona exploration (requires running app + LLM)",
            },
            "next_steps": [
                "Review compiled proposals for accuracy",
                "Apply emitted DSL patches to your project",
                "Re-run discovery to verify fixes",
            ],
        },
        "troubleshoot": {
            "name": "Troubleshooting Common Issues",
            "issues": [
                {
                    "problem": "No dazzle.toml found",
                    "solution": "Run commands from project root directory",
                },
                {
                    "problem": "Port already in use",
                    "solution": "Run 'dazzle stop' or use -p flag for different port",
                },
                {
                    "problem": "Docker not running",
                    "solution": "Start Docker or use 'dazzle serve --local'",
                },
                {
                    "problem": "Validation errors",
                    "solution": "Run 'dazzle validate' and fix syntax errors",
                },
                {
                    "problem": "Tests fail to find elements",
                    "solution": "Check data-dazzle-* attributes, use --headed to debug",
                },
                {
                    "problem": "Database locked",
                    "solution": "Stop any running 'dazzle serve' instances",
                },
                {
                    "problem": "Changes not appearing",
                    "solution": "Restart 'dazzle serve' - hot reload coming in v0.3.3",
                },
            ],
        },
    }

    workflow_normalized = workflow.lower().replace("-", "_").replace(" ", "_")

    if workflow_normalized in workflows:
        workflow_data = workflows[workflow_normalized]
        result: dict[str, Any] = {"workflow": workflow, "found": True}
        result.update(workflow_data)
        return result

    return {
        "workflow": workflow,
        "found": False,
        "available_workflows": list(workflows.keys()),
    }
