impl DemoRunner {
    fn create_demo_step(
        &self,
        name: &str,
        capability: &'static str,
        request: McpRequest,
        response: McpResponse,
        elapsed_ms: u64,
    ) -> DemoStep {
        let success = response.error.is_none();
        let output = if success {
            response.result.clone()
        } else {
            Some(
                json!({ "error": response.error.as_ref().map(|e| e.message.clone()).unwrap_or_default() }),
            )
        };

        DemoStep {
            name: name.to_string(),
            capability,
            request,
            response,
            elapsed_ms,
            success,
            output,
        }
    }

    #[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
    pub async fn execute(&mut self, repo_path: PathBuf) -> Result<DemoReport> {
        self.execute_with_diagram(&repo_path, None).await
    }

    #[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
    pub async fn execute_with_diagram(
        &mut self,
        repo_path: &Path,
        url: Option<&str>,
    ) -> Result<DemoReport> {
        let start = Instant::now();

        // Clone remote repository if URL provided or if path looks like a GitHub URL
        let (working_path, actual_url) = if let Some(url) = url {
            (self.clone_and_prepare(url).await?, Some(url.to_string()))
        } else if repo_path
            .to_string_lossy()
            .starts_with("https://github.com/")
        {
            // Handle case where GitHub URL is passed as path (from resolve_repo_spec)
            let url_str = repo_path.to_string_lossy().to_string();
            let cloned_path = self.clone_and_prepare(&url_str).await?;
            (cloned_path, Some(url_str))
        } else {
            (repo_path.to_path_buf(), None)
        };

        let version = env!("CARGO_PKG_VERSION");
        println!("🎯 PAIML MCP Agent Toolkit Demo v{version}");
        if let Some(ref url) = actual_url {
            println!("📁 Repository: {url} (cloned)");
        } else {
            println!("📁 Repository: {}", working_path.display());
        }
        println!();

        // Execute analysis pipeline with tracing
        let span = tracing::info_span!("demo_execution", repo = %working_path.display());
        let _guard = span.enter();

        // Collect all analysis results
        let mut steps = Vec::new();
        steps.push(self.demo_context_generation(&working_path).await?);
        steps.push(self.demo_complexity_analysis(&working_path).await?);
        steps.push(self.demo_dag_generation(&working_path).await?);
        steps.push(self.demo_churn_analysis(&working_path).await?);
        steps.push(self.demo_system_architecture(&working_path).await?);
        steps.push(self.demo_defect_analysis(&working_path).await?);
        steps.push(self.demo_template_generation(&working_path).await?);

        // Generate high-level system diagram
        let system_diagram = self.generate_system_diagram(&steps)?;

        let total_elapsed = start.elapsed().as_millis() as u64;

        Ok(DemoReport {
            repository: if let Some(ref url) = actual_url {
                url.clone()
            } else {
                working_path.display().to_string()
            },
            total_time_ms: total_elapsed,
            steps,
            system_diagram: Some(system_diagram),
            analysis: DemoAnalysisResult {
                files_analyzed: 50,
                functions_analyzed: 25,
                avg_complexity: 5.2,
                hotspot_functions: 3,
                quality_score: 0.85,
                tech_debt_hours: 8,
                qa_verification: Some("PASSED".to_string()),
                language_stats: Some(HashMap::new()),
                complexity_metrics: Some(HashMap::new()),
            },
            execution_time_ms: total_elapsed,
        })
    }

    async fn demo_context_generation(&mut self, path: &Path) -> Result<DemoStep> {
        let request = self.build_mcp_request(
            "generate_context",
            json!({
                "project_path": path.to_str().expect("Path must be valid UTF-8"),
                "toolchain": "rust",
                "format": "json"
            }),
        );

        println!("1️⃣  Generating AST Context...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "AST Context Analysis",
            "AST Context Analysis",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ Context generated in {elapsed} ms");
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    async fn demo_complexity_analysis(&mut self, path: &Path) -> Result<DemoStep> {
        let request = self.build_mcp_request(
            "analyze_complexity",
            json!({
                "project_path": path.to_str().expect("Path must be valid UTF-8"),
                "toolchain": "rust",
                "format": "summary",
                "max_cyclomatic": 20,
                "max_cognitive": 30
            }),
        );

        println!("\n2️⃣  Analyzing Code Complexity...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "Code Complexity Analysis",
            "Code Complexity Analysis",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ Complexity analyzed in {elapsed} ms");
            if let Some(result) = &response.result {
                if let Ok(summary) = serde_json::from_value::<Value>(result.clone()) {
                    if let Some(total_functions) = summary.get("total_functions") {
                        println!("   📊 Analyzed {total_functions} functions");
                    }
                }
            }
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    async fn demo_dag_generation(&mut self, path: &Path) -> Result<DemoStep> {
        let request = self.build_mcp_request(
            "analyze_dag",
            json!({
                "project_path": path.to_str().expect("Path must be valid UTF-8"),
                "dag_type": "import-graph",
                "filter_external": true,
                "show_complexity": true,
                "format": "mermaid"
            }),
        );

        println!("\n3️⃣  Generating Dependency Graph...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "DAG Generation",
            "DAG Visualization",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ DAG generated in {elapsed} ms");
            if let Some(result) = &response.result {
                if let Ok(dag_result) = serde_json::from_value::<Value>(result.clone()) {
                    if let Some(stats) = dag_result.get("stats") {
                        if let (Some(nodes), Some(edges)) = (stats.get("nodes"), stats.get("edges"))
                        {
                            println!("   📈 Graph: {nodes} nodes, {edges} edges");
                        }
                    }
                }
            }
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    async fn demo_churn_analysis(&mut self, path: &Path) -> Result<DemoStep> {
        let request = self.build_mcp_request(
            "analyze_code_churn",
            json!({
                "project_path": path.to_str().expect("Path must be valid UTF-8"),
                "period_days": 30,
                "format": "summary"
            }),
        );

        println!("\n4️⃣  Analyzing Code Churn...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "Code Churn Analysis",
            "Code Churn Analysis",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ Churn analyzed in {elapsed} ms");
            if let Some(result) = &response.result {
                if let Ok(churn_result) = serde_json::from_value::<Value>(result.clone()) {
                    if let Some(files_analyzed) = churn_result.get("files_analyzed") {
                        println!("   📈 Analyzed {files_analyzed} files");
                    }
                }
            }
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    async fn demo_system_architecture(&mut self, path: &Path) -> Result<DemoStep> {
        // Use the enhanced canonical query system
        let request = self.build_mcp_request(
            "analyze_system_architecture",
            json!({
                "project_path": path.to_str().expect("Path must be valid UTF-8"),
                "format": "mermaid",
                "show_complexity": true
            }),
        );

        println!("\n5️⃣  Analyzing System Architecture...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "System Architecture",
            "System Architecture Analysis",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ Architecture analyzed in {elapsed} ms");
            if let Some(result) = &response.result {
                if let Ok(arch_result) = serde_json::from_value::<Value>(result.clone()) {
                    if let Some(metadata) = arch_result.get("metadata") {
                        if let (Some(nodes), Some(edges)) =
                            (metadata.get("nodes"), metadata.get("edges"))
                        {
                            println!("   🏗️  Components: {nodes}, Relationships: {edges}");
                        }
                    }
                }
            }
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    async fn demo_defect_analysis(&mut self, path: &Path) -> Result<DemoStep> {
        let request = self.build_mcp_request(
            "analyze_defect_probability",
            json!({
                "project_path": path.to_str().expect("Path must be valid UTF-8"),
                "toolchain": "rust",
                "format": "summary"
            }),
        );

        println!("\n6️⃣  Analyzing Defect Probability...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "Defect Probability Analysis",
            "Defect Probability Analysis",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ Defect analysis completed in {elapsed} ms");
            if let Some(result) = &response.result {
                if let Ok(defect_result) = serde_json::from_value::<Value>(result.clone()) {
                    if let Some(avg_prob) = defect_result.get("average_probability") {
                        println!(
                            "   🔍 Average defect probability: {:.2}",
                            avg_prob.as_f64().unwrap_or(0.0)
                        );
                    }
                }
            }
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    async fn demo_template_generation(&mut self, path: &Path) -> Result<DemoStep> {
        let request = self.build_mcp_request(
            "generate_template",
            json!({
                "resource_uri": "template://makefile/rust/cli",
                "parameters": {
                    "project_name": path.file_name()
                        .unwrap_or_default()
                        .to_str()
                        .unwrap_or("demo-project"),
                    "has_tests": true,
                    "has_benchmarks": false
                }
            }),
        );

        println!("\n7️⃣  Generating Template...");

        let start = Instant::now();
        let response = handle_tool_call(self.server.clone(), request.clone()).await;
        let elapsed = start.elapsed().as_millis() as u64;

        let step = self.create_demo_step(
            "Template Generation",
            "Template Generation",
            request.clone(),
            response.clone(),
            elapsed,
        );

        self.execution_log.push(step.clone());

        if response.error.is_none() {
            println!("   ✅ Template generated in {elapsed} ms");
        } else {
            println!("   ❌ Failed: {:?}", response.error);
        }

        Ok(step)
    }

    fn build_mcp_request(&self, method: &str, arguments: Value) -> McpRequest {
        McpRequest {
            jsonrpc: "2.0".to_string(),
            id: json!(format!("demo-{}", method)),
            method: "tools/call".to_string(),
            params: Some(json!({
                "name": method,
                "arguments": arguments
            })),
        }
    }
}
