//! Transpilation Monitoring Engine for Depyler Agent Mode
//!
//! Provides file system watching and automatic transpilation for Python files,
//! with event-driven architecture for background agent operation.

use anyhow::Result;
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::sync::{mpsc, RwLock};
use tokio::time::interval;
use tracing::{debug, error, info};

/// Transpilation monitoring engine for automatic Python-to-Rust conversion
pub struct TranspilationMonitorEngine {
    /// Configuration
    config: TranspilationMonitorConfig,

    /// File system watchers by project
    watchers: Arc<RwLock<HashMap<String, RecommendedWatcher>>>,

    /// Current metrics by project
    metrics: Arc<RwLock<HashMap<String, TranspilationMetrics>>>,

    /// Event sender for transpilation updates
    event_sender: Option<mpsc::Sender<TranspilationEvent>>,

    /// Event receiver for external consumption
    event_receiver: Option<mpsc::Receiver<TranspilationEvent>>,
}

/// Configuration for transpilation monitoring
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TranspilationMonitorConfig {
    /// Update interval for periodic checks
    pub update_interval: Duration,

    /// File patterns to watch for transpilation
    pub watch_patterns: Vec<String>,

    /// Debounce interval to avoid excessive transpilations
    pub debounce_interval: Duration,

    /// Maximum number of files to transpile per batch
    pub max_batch_size: usize,

    /// Auto-transpile on file changes
    pub auto_transpile: bool,

    /// Verification level for transpiled code
    pub verification_level: String,
}

impl Default for TranspilationMonitorConfig {
    fn default() -> Self {
        Self {
            update_interval: Duration::from_secs(2),
            watch_patterns: vec!["**/*.py".to_string()],
            debounce_interval: Duration::from_millis(500),
            max_batch_size: 20,
            auto_transpile: true,
            verification_level: "basic".to_string(),
        }
    }
}

/// Transpilation metrics for a project
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TranspilationMetrics {
    /// Project identifier
    pub project_id: String,

    /// Last update timestamp
    pub last_updated: SystemTime,

    /// Total files transpiled
    pub files_transpiled: u64,

    /// Successful transpilations
    pub successful_transpilations: u64,

    /// Failed transpilations
    pub failed_transpilations: u64,

    /// Average transpilation time (milliseconds)
    pub avg_transpilation_time_ms: u64,

    /// Total Python lines processed
    pub total_python_lines: usize,

    /// Total Rust lines generated
    pub total_rust_lines: usize,

    /// Last error message (if any)
    pub last_error: Option<String>,
}

impl Default for TranspilationMetrics {
    fn default() -> Self {
        Self {
            project_id: String::new(),
            last_updated: SystemTime::now(),
            files_transpiled: 0,
            successful_transpilations: 0,
            failed_transpilations: 0,
            avg_transpilation_time_ms: 0,
            total_python_lines: 0,
            total_rust_lines: 0,
            last_error: None,
        }
    }
}

/// Events generated by the transpilation monitor
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TranspilationEvent {
    /// Python file was changed and needs transpilation
    FileChanged {
        /// Project identifier
        project_id: String,
        /// File path that changed
        path: PathBuf,
        /// Event type (modified, created, deleted)
        event_type: FileEventType,
        /// Timestamp of the event
        timestamp: SystemTime,
    },

    /// File was successfully transpiled
    TranspilationSucceeded {
        /// Project identifier
        project_id: String,
        /// Python file path
        python_file: PathBuf,
        /// Generated Rust file path
        rust_file: PathBuf,
        /// Transpilation time in milliseconds
        transpilation_time_ms: u64,
        /// Lines of Python code
        python_lines: usize,
        /// Lines of generated Rust code
        rust_lines: usize,
    },

    /// File transpilation failed
    TranspilationFailed {
        /// Project identifier
        project_id: String,
        /// Python file path
        python_file: PathBuf,
        /// Error message
        error: String,
        /// Timestamp of the failure
        timestamp: SystemTime,
    },

    /// Project was added to monitoring
    ProjectAdded {
        /// Project identifier
        project_id: String,
        /// Project path
        path: PathBuf,
        /// Watch patterns
        patterns: Vec<String>,
    },

    /// Project was removed from monitoring
    ProjectRemoved {
        /// Project identifier
        project_id: String,
    },

    /// Periodic status update
    StatusUpdate {
        /// Overall metrics
        metrics: HashMap<String, TranspilationMetrics>,
        /// Timestamp of the update
        timestamp: SystemTime,
    },
}

/// Types of file system events
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FileEventType {
    /// File was created
    Created,
    /// File was modified
    Modified,
    /// File was deleted
    Deleted,
    /// File was renamed
    Renamed,
}

impl TranspilationMonitorEngine {
    /// Create a new transpilation monitor engine
    pub async fn new(config: TranspilationMonitorConfig) -> Result<Self> {
        let (event_sender, event_receiver) = mpsc::channel(1000);

        Ok(Self {
            config,
            watchers: Arc::new(RwLock::new(HashMap::new())),
            metrics: Arc::new(RwLock::new(HashMap::new())),
            event_sender: Some(event_sender),
            event_receiver: Some(event_receiver),
        })
    }

    /// Start monitoring a project
    pub async fn add_project(
        &mut self,
        project_id: String,
        path: PathBuf,
        patterns: Vec<String>,
    ) -> Result<()> {
        info!(
            "Adding project '{}' to transpilation monitoring at {}",
            project_id,
            path.display()
        );

        // Create file system watcher
        let event_sender = self.event_sender.clone().unwrap();
        let project_id_clone = project_id.clone();
        let (tx, mut rx) = mpsc::channel(100);

        let mut watcher = RecommendedWatcher::new(
            move |res: notify::Result<Event>| {
                if let Ok(event) = res {
                    let _ = tx.try_send(event);
                }
            },
            Config::default(),
        )?;

        // Start watching the project directory
        watcher.watch(&path, RecursiveMode::Recursive)?;

        // Spawn event handler for this project
        let project_path = path.clone();
        let watch_patterns = patterns.clone();
        tokio::spawn(async move {
            while let Some(event) = rx.recv().await {
                if let Err(e) = Self::handle_fs_event(
                    &event_sender,
                    &project_id_clone,
                    &project_path,
                    &watch_patterns,
                    event,
                )
                .await
                {
                    error!("Failed to handle file system event: {}", e);
                }
            }
        });

        // Store the watcher
        {
            let mut watchers = self.watchers.write().await;
            watchers.insert(project_id.clone(), watcher);
        }

        // Initialize metrics for this project
        {
            let mut metrics = self.metrics.write().await;
            metrics.insert(
                project_id.clone(),
                TranspilationMetrics {
                    project_id: project_id.clone(),
                    ..Default::default()
                },
            );
        }

        // Send project added event
        if let Some(ref sender) = self.event_sender {
            let _ = sender
                .send(TranspilationEvent::ProjectAdded {
                    project_id,
                    path,
                    patterns,
                })
                .await;
        }

        Ok(())
    }

    /// Stop monitoring a project
    pub async fn remove_project(&mut self, project_id: &str) -> Result<()> {
        info!(
            "Removing project '{}' from transpilation monitoring",
            project_id
        );

        // Remove watcher
        {
            let mut watchers = self.watchers.write().await;
            watchers.remove(project_id);
        }

        // Remove metrics
        {
            let mut metrics = self.metrics.write().await;
            metrics.remove(project_id);
        }

        // Send project removed event
        if let Some(ref sender) = self.event_sender {
            let _ = sender
                .send(TranspilationEvent::ProjectRemoved {
                    project_id: project_id.to_string(),
                })
                .await;
        }

        Ok(())
    }

    /// Get metrics for a specific project
    pub async fn get_project_metrics(&self, project_id: &str) -> Option<TranspilationMetrics> {
        let metrics = self.metrics.read().await;
        metrics.get(project_id).cloned()
    }

    /// Get metrics for all projects
    pub async fn get_all_metrics(&self) -> HashMap<String, TranspilationMetrics> {
        let metrics = self.metrics.read().await;
        metrics.clone()
    }

    /// Get event receiver for consuming transpilation events
    pub fn get_event_receiver(&mut self) -> mpsc::Receiver<TranspilationEvent> {
        self.event_receiver.take().unwrap()
    }

    /// Handle file system events
    async fn handle_fs_event(
        event_sender: &mpsc::Sender<TranspilationEvent>,
        project_id: &str,
        _project_path: &PathBuf,
        watch_patterns: &[String],
        event: Event,
    ) -> Result<()> {
        debug!("File system event: {:?}", event);

        // Filter for relevant events
        let event_type = match event.kind {
            EventKind::Create(_) => FileEventType::Created,
            EventKind::Modify(_) => FileEventType::Modified,
            EventKind::Remove(_) => FileEventType::Deleted,
            _ => return Ok(()), // Ignore other event types
        };

        // Process each path in the event
        for path in &event.paths {
            // Check if this is a Python file
            if !Self::matches_patterns(path, watch_patterns) {
                continue;
            }

            // Don't process deleted files
            if matches!(event_type, FileEventType::Deleted) {
                continue;
            }

            // Send file changed event
            let _ = event_sender
                .send(TranspilationEvent::FileChanged {
                    project_id: project_id.to_string(),
                    path: path.clone(),
                    event_type: event_type.clone(),
                    timestamp: SystemTime::now(),
                })
                .await;
        }

        Ok(())
    }

    /// Check if a path matches any of the watch patterns
    fn matches_patterns(path: &Path, patterns: &[String]) -> bool {
        // Simple implementation - in practice would use glob patterns
        for pattern in patterns {
            if pattern == "**/*.py" && path.extension().and_then(|s| s.to_str()) == Some("py") {
                return true;
            }
        }
        false
    }

    /// Update metrics for a project
    pub async fn update_metrics(
        &self,
        project_id: &str,
        transpilation_success: bool,
        transpilation_time_ms: u64,
        python_lines: usize,
        rust_lines: usize,
        error_message: Option<String>,
    ) {
        let mut metrics = self.metrics.write().await;
        if let Some(project_metrics) = metrics.get_mut(project_id) {
            project_metrics.last_updated = SystemTime::now();
            project_metrics.files_transpiled += 1;

            if transpilation_success {
                project_metrics.successful_transpilations += 1;
                project_metrics.total_python_lines += python_lines;
                project_metrics.total_rust_lines += rust_lines;

                // Update average transpilation time
                let total_time = project_metrics.avg_transpilation_time_ms
                    * (project_metrics.successful_transpilations - 1)
                    + transpilation_time_ms;
                project_metrics.avg_transpilation_time_ms =
                    total_time / project_metrics.successful_transpilations;
            } else {
                project_metrics.failed_transpilations += 1;
                project_metrics.last_error = error_message;
            }
        }
    }

    /// Start periodic status updates
    pub async fn start_status_updates(&self) -> Result<()> {
        let mut interval = interval(self.config.update_interval);
        let event_sender = self.event_sender.clone().unwrap();
        let metrics = Arc::clone(&self.metrics);

        tokio::spawn(async move {
            loop {
                interval.tick().await;

                let current_metrics = {
                    let metrics = metrics.read().await;
                    metrics.clone()
                };

                let _ = event_sender
                    .send(TranspilationEvent::StatusUpdate {
                        metrics: current_metrics,
                        timestamp: SystemTime::now(),
                    })
                    .await;
            }
        });

        Ok(())
    }

    /// Shutdown the transpilation monitor
    pub async fn shutdown(&mut self) -> Result<()> {
        info!("Shutting down transpilation monitor...");

        // Clear all watchers
        {
            let mut watchers = self.watchers.write().await;
            watchers.clear();
        }

        // Clear metrics
        {
            let mut metrics = self.metrics.write().await;
            metrics.clear();
        }

        info!("Transpilation monitor shut down successfully");
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // Test TranspilationMonitorConfig
    #[test]
    fn test_transpilation_monitor_config_default() {
        let config = TranspilationMonitorConfig::default();
        assert_eq!(config.update_interval, Duration::from_secs(2));
        assert_eq!(config.watch_patterns, vec!["**/*.py".to_string()]);
        assert_eq!(config.debounce_interval, Duration::from_millis(500));
        assert_eq!(config.max_batch_size, 20);
        assert!(config.auto_transpile);
        assert_eq!(config.verification_level, "basic");
    }

    #[test]
    fn test_transpilation_monitor_config_serialization() {
        let config = TranspilationMonitorConfig::default();
        let json = serde_json::to_string(&config).unwrap();
        assert!(json.contains("update_interval"));
        assert!(json.contains("watch_patterns"));
    }

    #[test]
    fn test_transpilation_monitor_config_deserialization() {
        let config = TranspilationMonitorConfig::default();
        let json = serde_json::to_string(&config).unwrap();
        let deserialized: TranspilationMonitorConfig = serde_json::from_str(&json).unwrap();
        assert_eq!(config.max_batch_size, deserialized.max_batch_size);
    }

    #[test]
    fn test_transpilation_monitor_config_clone() {
        let config = TranspilationMonitorConfig::default();
        let cloned = config.clone();
        assert_eq!(config.max_batch_size, cloned.max_batch_size);
    }

    #[test]
    fn test_transpilation_monitor_config_debug() {
        let config = TranspilationMonitorConfig::default();
        let debug = format!("{:?}", config);
        assert!(debug.contains("update_interval"));
    }

    // Test TranspilationMetrics
    #[test]
    fn test_transpilation_metrics_default() {
        let metrics = TranspilationMetrics::default();
        assert_eq!(metrics.project_id, "");
        assert_eq!(metrics.files_transpiled, 0);
        assert_eq!(metrics.successful_transpilations, 0);
        assert_eq!(metrics.failed_transpilations, 0);
        assert_eq!(metrics.avg_transpilation_time_ms, 0);
        assert_eq!(metrics.total_python_lines, 0);
        assert_eq!(metrics.total_rust_lines, 0);
        assert!(metrics.last_error.is_none());
    }

    #[test]
    fn test_transpilation_metrics_with_project() {
        let metrics = TranspilationMetrics {
            project_id: "test_project".to_string(),
            files_transpiled: 10,
            successful_transpilations: 8,
            failed_transpilations: 2,
            avg_transpilation_time_ms: 150,
            total_python_lines: 1000,
            total_rust_lines: 800,
            last_error: Some("Test error".to_string()),
            ..Default::default()
        };

        assert_eq!(metrics.project_id, "test_project");
        assert_eq!(metrics.files_transpiled, 10);
        assert_eq!(metrics.successful_transpilations, 8);
        assert_eq!(metrics.failed_transpilations, 2);
    }

    #[test]
    fn test_transpilation_metrics_serialization() {
        let metrics = TranspilationMetrics::default();
        let json = serde_json::to_string(&metrics).unwrap();
        assert!(json.contains("project_id"));
        assert!(json.contains("files_transpiled"));
    }

    #[test]
    fn test_transpilation_metrics_clone() {
        let metrics = TranspilationMetrics::default();
        let cloned = metrics.clone();
        assert_eq!(metrics.project_id, cloned.project_id);
    }

    #[test]
    fn test_transpilation_metrics_debug() {
        let metrics = TranspilationMetrics::default();
        let debug = format!("{:?}", metrics);
        assert!(debug.contains("project_id"));
    }

    // Test FileEventType
    #[test]
    fn test_file_event_type_variants() {
        let created = FileEventType::Created;
        let modified = FileEventType::Modified;
        let deleted = FileEventType::Deleted;
        let renamed = FileEventType::Renamed;

        assert!(format!("{:?}", created).contains("Created"));
        assert!(format!("{:?}", modified).contains("Modified"));
        assert!(format!("{:?}", deleted).contains("Deleted"));
        assert!(format!("{:?}", renamed).contains("Renamed"));
    }

    #[test]
    fn test_file_event_type_serialization() {
        let event_type = FileEventType::Modified;
        let json = serde_json::to_string(&event_type).unwrap();
        assert!(json.contains("Modified"));
    }

    #[test]
    fn test_file_event_type_deserialization() {
        let json = r#""Created""#;
        let event_type: FileEventType = serde_json::from_str(json).unwrap();
        assert!(matches!(event_type, FileEventType::Created));
    }

    #[test]
    fn test_file_event_type_clone() {
        let event_type = FileEventType::Modified;
        let cloned = event_type.clone();
        assert!(matches!(cloned, FileEventType::Modified));
    }

    // Test TranspilationEvent
    #[test]
    fn test_transpilation_event_file_changed() {
        let event = TranspilationEvent::FileChanged {
            project_id: "test".to_string(),
            path: PathBuf::from("/tmp/test.py"),
            event_type: FileEventType::Modified,
            timestamp: SystemTime::now(),
        };

        if let TranspilationEvent::FileChanged { project_id, path, .. } = event {
            assert_eq!(project_id, "test");
            assert_eq!(path, PathBuf::from("/tmp/test.py"));
        } else {
            panic!("Expected FileChanged event");
        }
    }

    #[test]
    fn test_transpilation_event_succeeded() {
        let event = TranspilationEvent::TranspilationSucceeded {
            project_id: "test".to_string(),
            python_file: PathBuf::from("/tmp/test.py"),
            rust_file: PathBuf::from("/tmp/test.rs"),
            transpilation_time_ms: 100,
            python_lines: 50,
            rust_lines: 60,
        };

        if let TranspilationEvent::TranspilationSucceeded { transpilation_time_ms, python_lines, rust_lines, .. } = event {
            assert_eq!(transpilation_time_ms, 100);
            assert_eq!(python_lines, 50);
            assert_eq!(rust_lines, 60);
        } else {
            panic!("Expected TranspilationSucceeded event");
        }
    }

    #[test]
    fn test_transpilation_event_failed() {
        let event = TranspilationEvent::TranspilationFailed {
            project_id: "test".to_string(),
            python_file: PathBuf::from("/tmp/test.py"),
            error: "Transpilation error".to_string(),
            timestamp: SystemTime::now(),
        };

        if let TranspilationEvent::TranspilationFailed { error, .. } = event {
            assert_eq!(error, "Transpilation error");
        } else {
            panic!("Expected TranspilationFailed event");
        }
    }

    #[test]
    fn test_transpilation_event_project_added() {
        let event = TranspilationEvent::ProjectAdded {
            project_id: "new_project".to_string(),
            path: PathBuf::from("/home/user/project"),
            patterns: vec!["**/*.py".to_string()],
        };

        if let TranspilationEvent::ProjectAdded { project_id, patterns, .. } = event {
            assert_eq!(project_id, "new_project");
            assert_eq!(patterns.len(), 1);
        } else {
            panic!("Expected ProjectAdded event");
        }
    }

    #[test]
    fn test_transpilation_event_project_removed() {
        let event = TranspilationEvent::ProjectRemoved {
            project_id: "removed_project".to_string(),
        };

        if let TranspilationEvent::ProjectRemoved { project_id } = event {
            assert_eq!(project_id, "removed_project");
        } else {
            panic!("Expected ProjectRemoved event");
        }
    }

    #[test]
    fn test_transpilation_event_status_update() {
        let mut metrics = HashMap::new();
        metrics.insert("project1".to_string(), TranspilationMetrics::default());

        let event = TranspilationEvent::StatusUpdate {
            metrics: metrics.clone(),
            timestamp: SystemTime::now(),
        };

        if let TranspilationEvent::StatusUpdate { metrics: m, .. } = event {
            assert_eq!(m.len(), 1);
        } else {
            panic!("Expected StatusUpdate event");
        }
    }

    #[test]
    fn test_transpilation_event_serialization() {
        let event = TranspilationEvent::ProjectAdded {
            project_id: "test".to_string(),
            path: PathBuf::from("/tmp"),
            patterns: vec!["**/*.py".to_string()],
        };
        let json = serde_json::to_string(&event).unwrap();
        assert!(json.contains("ProjectAdded"));
    }

    #[test]
    fn test_transpilation_event_clone() {
        let event = TranspilationEvent::ProjectRemoved {
            project_id: "test".to_string(),
        };
        let cloned = event.clone();

        if let TranspilationEvent::ProjectRemoved { project_id } = cloned {
            assert_eq!(project_id, "test");
        }
    }

    // Test TranspilationMonitorEngine
    #[tokio::test]
    async fn test_transpilation_monitor_engine_new() {
        let config = TranspilationMonitorConfig::default();
        let result = TranspilationMonitorEngine::new(config).await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_transpilation_monitor_engine_get_all_metrics_empty() {
        let config = TranspilationMonitorConfig::default();
        let monitor = TranspilationMonitorEngine::new(config).await.unwrap();
        let metrics = monitor.get_all_metrics().await;
        assert!(metrics.is_empty());
    }

    #[tokio::test]
    async fn test_transpilation_monitor_engine_get_project_metrics_none() {
        let config = TranspilationMonitorConfig::default();
        let monitor = TranspilationMonitorEngine::new(config).await.unwrap();
        let metrics = monitor.get_project_metrics("nonexistent").await;
        assert!(metrics.is_none());
    }

    #[tokio::test]
    async fn test_transpilation_monitor_engine_shutdown() {
        let config = TranspilationMonitorConfig::default();
        let mut monitor = TranspilationMonitorEngine::new(config).await.unwrap();
        let result = monitor.shutdown().await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_transpilation_monitor_engine_update_metrics() {
        let config = TranspilationMonitorConfig::default();
        let monitor = TranspilationMonitorEngine::new(config).await.unwrap();

        // Initialize metrics with a project
        {
            let mut metrics = monitor.metrics.write().await;
            metrics.insert(
                "test_project".to_string(),
                TranspilationMetrics {
                    project_id: "test_project".to_string(),
                    ..Default::default()
                },
            );
        }

        // Update metrics
        monitor
            .update_metrics("test_project", true, 100, 50, 60, None)
            .await;

        let project_metrics = monitor.get_project_metrics("test_project").await.unwrap();
        assert_eq!(project_metrics.files_transpiled, 1);
        assert_eq!(project_metrics.successful_transpilations, 1);
        assert_eq!(project_metrics.total_python_lines, 50);
        assert_eq!(project_metrics.total_rust_lines, 60);
    }

    #[tokio::test]
    async fn test_transpilation_monitor_engine_update_metrics_failure() {
        let config = TranspilationMonitorConfig::default();
        let monitor = TranspilationMonitorEngine::new(config).await.unwrap();

        // Initialize metrics with a project
        {
            let mut metrics = monitor.metrics.write().await;
            metrics.insert(
                "test_project".to_string(),
                TranspilationMetrics {
                    project_id: "test_project".to_string(),
                    ..Default::default()
                },
            );
        }

        // Update metrics with failure
        monitor
            .update_metrics(
                "test_project",
                false,
                0,
                0,
                0,
                Some("Test error".to_string()),
            )
            .await;

        let project_metrics = monitor.get_project_metrics("test_project").await.unwrap();
        assert_eq!(project_metrics.files_transpiled, 1);
        assert_eq!(project_metrics.failed_transpilations, 1);
        assert_eq!(project_metrics.last_error, Some("Test error".to_string()));
    }

    // Test matches_patterns helper
    #[test]
    fn test_matches_patterns_python_file() {
        let patterns = vec!["**/*.py".to_string()];
        let path = Path::new("/tmp/test.py");
        assert!(TranspilationMonitorEngine::matches_patterns(path, &patterns));
    }

    #[test]
    fn test_matches_patterns_non_python_file() {
        let patterns = vec!["**/*.py".to_string()];
        let path = Path::new("/tmp/test.rs");
        assert!(!TranspilationMonitorEngine::matches_patterns(path, &patterns));
    }

    #[test]
    fn test_matches_patterns_no_extension() {
        let patterns = vec!["**/*.py".to_string()];
        let path = Path::new("/tmp/test");
        assert!(!TranspilationMonitorEngine::matches_patterns(path, &patterns));
    }

    #[test]
    fn test_matches_patterns_empty_patterns() {
        let patterns: Vec<String> = vec![];
        let path = Path::new("/tmp/test.py");
        assert!(!TranspilationMonitorEngine::matches_patterns(path, &patterns));
    }

    // Test metrics round trip
    #[test]
    fn test_transpilation_metrics_round_trip() {
        let metrics = TranspilationMetrics {
            project_id: "round_trip_test".to_string(),
            files_transpiled: 100,
            successful_transpilations: 95,
            failed_transpilations: 5,
            avg_transpilation_time_ms: 150,
            total_python_lines: 5000,
            total_rust_lines: 4500,
            last_error: Some("Last error".to_string()),
            ..Default::default()
        };

        let json = serde_json::to_string(&metrics).unwrap();
        let deserialized: TranspilationMetrics = serde_json::from_str(&json).unwrap();

        assert_eq!(metrics.project_id, deserialized.project_id);
        assert_eq!(metrics.files_transpiled, deserialized.files_transpiled);
        assert_eq!(metrics.successful_transpilations, deserialized.successful_transpilations);
        assert_eq!(metrics.failed_transpilations, deserialized.failed_transpilations);
        assert_eq!(metrics.last_error, deserialized.last_error);
    }

    // Test config round trip
    #[test]
    fn test_transpilation_monitor_config_round_trip() {
        let config = TranspilationMonitorConfig {
            update_interval: Duration::from_secs(5),
            watch_patterns: vec!["**/*.py".to_string(), "**/*.pyw".to_string()],
            debounce_interval: Duration::from_millis(1000),
            max_batch_size: 50,
            auto_transpile: false,
            verification_level: "full".to_string(),
        };

        let json = serde_json::to_string(&config).unwrap();
        let deserialized: TranspilationMonitorConfig = serde_json::from_str(&json).unwrap();

        assert_eq!(config.max_batch_size, deserialized.max_batch_size);
        assert_eq!(config.auto_transpile, deserialized.auto_transpile);
        assert_eq!(config.verification_level, deserialized.verification_level);
    }
}
