#[cfg(test)]
#[allow(clippy::module_inception)]
mod tests {
    use std::collections::HashMap;
    use std::path::PathBuf;

    use tempfile::TempDir;

    use crate::tools::guidance::*;

    fn create_test_system_status() -> SystemStatus {
        let paths = SystemPaths {
            provisioning_root: PathBuf::from("/test"),
            workspace_dir: Some(PathBuf::from("/test/workspace")),
            docs_dir: PathBuf::from("/test/docs"),
            config_dir: PathBuf::from("/test/config"),
        };

        SystemStatus {
            nushell_version: Some("0.107.1".to_string()),
            workspace_configured: true,
            providers: vec!["aws".to_string(), "upcloud".to_string()],
            orchestrator_running: true,
            services_status: HashMap::new(),
            issues: Vec::new(),
            paths,
            metadata: HashMap::new(),
        }
    }

    #[test]
    fn test_system_status_creation() {
        let status = create_test_system_status();
        assert!(status.nushell_version.is_some());
        assert_eq!(status.providers.len(), 2);
        assert!(status.workspace_configured);
        assert!(status.orchestrator_running);
    }

    #[test]
    fn test_issue_severity_ordering() {
        assert!(IssueSeverity::Critical > IssueSeverity::Error);
        assert!(IssueSeverity::Error > IssueSeverity::Warning);
        assert!(IssueSeverity::Warning > IssueSeverity::Info);
    }

    #[test]
    fn test_health_status_variants() {
        let statuses = [
            HealthStatus::Healthy,
            HealthStatus::Degraded,
            HealthStatus::Unhealthy,
            HealthStatus::Unknown,
        ];

        assert_eq!(statuses.len(), 4);
        assert_eq!(HealthStatus::Healthy, HealthStatus::Healthy);
    }

    #[test]
    fn test_risk_level_variants() {
        let risk_low = RiskLevel::Low;
        let risk_medium = RiskLevel::Medium;
        let risk_high = RiskLevel::High;

        assert_eq!(risk_low, RiskLevel::Low);
        assert_ne!(risk_low, risk_high);
    }

    #[test]
    fn test_next_action_priority() {
        let action = NextAction {
            command: "test".to_string(),
            description: "test action".to_string(),
            docs_link: "docs/test.md".to_string(),
            expected_outcome: "success".to_string(),
            priority: 1,
        };

        assert_eq!(action.priority, 1);
        assert!(!action.command.is_empty());
    }

    #[test]
    fn test_doc_reference_relevance() {
        let doc = DocReference {
            path: "docs/test.md".to_string(),
            title: "Test Document".to_string(),
            snippet: "This is a test snippet".to_string(),
            relevance: 0.95,
            section: Some("Introduction".to_string()),
        };

        assert!(doc.relevance > 0.9);
        assert!(doc.relevance <= 1.0);
    }

    #[test]
    fn test_validation_result_with_errors() {
        let result = ValidationResult {
            valid: false,
            errors: vec![ValidationError {
                message: "Test error".to_string(),
                path: "config.toml".to_string(),
                line: Some(10),
                fix: Some("Fix it".to_string()),
            }],
            warnings: Vec::new(),
            suggestions: Vec::new(),
            docs: Vec::new(),
        };

        assert!(!result.valid);
        assert_eq!(result.errors.len(), 1);
        assert_eq!(result.errors[0].line, Some(10));
    }

    #[test]
    fn test_diagnosis_with_fixes() {
        let diagnosis = Diagnosis {
            error: "Nushell not found".to_string(),
            root_cause: "Nushell is not installed".to_string(),
            fixes: vec![Fix {
                description: "Install Nushell".to_string(),
                commands: vec!["brew install nushell".to_string()],
                expected_outcome: "Nushell installed".to_string(),
                risk: RiskLevel::Low,
            }],
            related_docs: Vec::new(),
            confidence: 0.95,
        };

        assert_eq!(diagnosis.fixes.len(), 1);
        assert!(diagnosis.confidence > 0.9);
        assert_eq!(diagnosis.fixes[0].risk, RiskLevel::Low);
    }

    #[test]
    fn test_system_status_tool_creation() {
        let _tool = SystemStatusTool::new(PathBuf::from("/test"));
        // Tool created successfully - type check is the test
    }

    #[test]
    fn test_next_action_tool_creation() {
        let _tool = NextActionTool::new(PathBuf::from("/test"));
        // Tool created successfully - type check is the test
    }

    #[test]
    fn test_doc_finder_tool_creation() {
        let _tool = DocFinderTool::new(PathBuf::from("/test"));
        // Tool created successfully - type check is the test
    }

    #[test]
    fn test_troubleshooter_tool_creation() {
        let _tool = TroubleshooterTool::new(PathBuf::from("/test"));
        // Tool created successfully - type check is the test
    }

    #[test]
    fn test_config_validator_tool_creation() {
        let _tool = ConfigValidatorTool::new(PathBuf::from("/test"));
        // Tool created successfully - type check is the test
    }

    #[test]
    fn test_system_status_with_issues() {
        let mut status = create_test_system_status();
        status.issues.push(Issue {
            severity: IssueSeverity::Warning,
            category: "Configuration".to_string(),
            description: "Test warning".to_string(),
            fix: Some("Run command".to_string()),
            docs_link: Some("docs/help.md".to_string()),
        });

        assert_eq!(status.issues.len(), 1);
        assert_eq!(status.issues[0].severity, IssueSeverity::Warning);
    }

    #[test]
    fn test_service_status_healthy() {
        let service = ServiceStatus {
            name: "orchestrator".to_string(),
            running: true,
            version: Some("1.0.0".to_string()),
            health: HealthStatus::Healthy,
            last_checked: "2025-10-10T00:00:00Z".to_string(),
        };

        assert!(service.running);
        assert_eq!(service.health, HealthStatus::Healthy);
        assert!(service.version.is_some());
    }

    #[test]
    fn test_next_action_tool_suggest_with_critical_issue() {
        let tool = NextActionTool::new(PathBuf::from("/test"));
        let mut status = create_test_system_status();

        // Add critical issue
        status.issues.push(Issue {
            severity: IssueSeverity::Critical,
            category: "Prerequisites".to_string(),
            description: "Nushell not installed".to_string(),
            fix: Some("brew install nushell".to_string()),
            docs_link: Some("docs/setup.md".to_string()),
        });

        let result = tool.suggest_next_action(&status);
        assert!(result.is_ok());

        let action = result.unwrap();
        assert_eq!(action.priority, 1);
        assert!(action.command.contains("brew install nushell"));
    }

    #[test]
    fn test_next_action_tool_workspace_not_configured() {
        let tool = NextActionTool::new(PathBuf::from("/test"));
        let mut status = create_test_system_status();
        status.workspace_configured = false;

        let result = tool.suggest_next_action(&status);
        assert!(result.is_ok());

        let action = result.unwrap();
        assert_eq!(action.priority, 2);
        assert!(action.command.contains("workspace init"));
    }

    #[test]
    fn test_next_action_tool_no_providers() {
        let tool = NextActionTool::new(PathBuf::from("/test"));
        let mut status = create_test_system_status();
        status.providers.clear();

        let result = tool.suggest_next_action(&status);
        assert!(result.is_ok());

        let action = result.unwrap();
        assert_eq!(action.priority, 3);
        assert!(action.command.contains("discover providers"));
    }

    #[test]
    fn test_next_action_tool_orchestrator_not_running() {
        let tool = NextActionTool::new(PathBuf::from("/test"));
        let mut status = create_test_system_status();
        status.orchestrator_running = false;

        let result = tool.suggest_next_action(&status);
        assert!(result.is_ok());

        let action = result.unwrap();
        assert_eq!(action.priority, 4);
        assert!(action.command.contains("orchestrator"));
    }

    #[test]
    fn test_troubleshooter_nushell_error() {
        let tool = TroubleshooterTool::new(PathBuf::from("/test"));
        let status = create_test_system_status();

        let result = tool.diagnose_issue("command not found: nu", &status);
        assert!(result.is_ok());

        let diagnosis = result.unwrap();
        assert!(diagnosis.confidence > 0.9);
        assert!(diagnosis.root_cause.contains("Nushell"));
        assert!(!diagnosis.fixes.is_empty());
    }

    #[test]
    fn test_troubleshooter_workspace_error() {
        let tool = TroubleshooterTool::new(PathBuf::from("/test"));
        let status = create_test_system_status();

        let result = tool.diagnose_issue("workspace not found", &status);
        assert!(result.is_ok());

        let diagnosis = result.unwrap();
        assert!(diagnosis.confidence > 0.8);
        assert!(diagnosis.fixes.iter().any(|f| f
            .commands
            .iter()
            .any(|c: &String| c.contains("workspace init"))));
    }

    #[test]
    fn test_troubleshooter_orchestrator_error() {
        let tool = TroubleshooterTool::new(PathBuf::from("/test"));
        let status = create_test_system_status();

        let result = tool.diagnose_issue("connection refused to orchestrator", &status);
        assert!(result.is_ok());

        let diagnosis = result.unwrap();
        assert!(diagnosis.confidence > 0.8);
        assert!(diagnosis
            .fixes
            .iter()
            .any(|f| f.description.contains("orchestrator")));
    }

    #[test]
    fn test_troubleshooter_provider_error() {
        let tool = TroubleshooterTool::new(PathBuf::from("/test"));
        let status = create_test_system_status();

        let result = tool.diagnose_issue("provider aws not configured", &status);
        assert!(result.is_ok());

        let diagnosis = result.unwrap();
        assert!(!diagnosis.fixes.is_empty());
    }

    #[test]
    fn test_config_validator_nonexistent_file() {
        let tool = ConfigValidatorTool::new(PathBuf::from("/test"));
        let result = tool.validate_config("nonexistent.toml");

        assert!(result.is_ok());
        let validation = result.unwrap();
        assert!(!validation.valid);
        assert!(!validation.errors.is_empty());
    }

    #[test]
    fn test_multiple_next_actions() {
        let tool = NextActionTool::new(PathBuf::from("/test"));
        let mut status = create_test_system_status();

        // Add multiple issues
        status.issues.push(Issue {
            severity: IssueSeverity::Critical,
            category: "Prerequisites".to_string(),
            description: "Critical issue 1".to_string(),
            fix: Some("fix 1".to_string()),
            docs_link: None,
        });
        status.issues.push(Issue {
            severity: IssueSeverity::Critical,
            category: "Prerequisites".to_string(),
            description: "Critical issue 2".to_string(),
            fix: Some("fix 2".to_string()),
            docs_link: None,
        });

        let result = tool.suggest_multiple_actions(&status, 3);
        assert!(result.is_ok());

        let actions = result.unwrap();
        assert!(actions.len() <= 3);
        assert!(actions.iter().all(|a| a.priority <= 2));
    }

    #[test]
    fn test_system_paths_structure() {
        let paths = SystemPaths {
            provisioning_root: PathBuf::from("/usr/local/provisioning"),
            workspace_dir: Some(PathBuf::from("/workspace")),
            docs_dir: PathBuf::from("/usr/local/provisioning/docs"),
            config_dir: PathBuf::from("/usr/local/provisioning/config"),
        };

        assert_eq!(
            paths.provisioning_root,
            PathBuf::from("/usr/local/provisioning")
        );
        assert!(paths.workspace_dir.is_some());
    }

    #[test]
    fn test_fix_risk_levels() {
        let low_risk_fix = Fix {
            description: "Safe fix".to_string(),
            commands: vec!["echo test".to_string()],
            expected_outcome: "Success".to_string(),
            risk: RiskLevel::Low,
        };

        let high_risk_fix = Fix {
            description: "Dangerous fix".to_string(),
            commands: vec!["rm -rf /".to_string()],
            expected_outcome: "Disaster".to_string(),
            risk: RiskLevel::High,
        };

        assert_eq!(low_risk_fix.risk, RiskLevel::Low);
        assert_eq!(high_risk_fix.risk, RiskLevel::High);
        assert_ne!(low_risk_fix.risk, high_risk_fix.risk);
    }

    #[test]
    fn test_validation_with_warnings_only() {
        let result = ValidationResult {
            valid: true,
            errors: Vec::new(),
            warnings: vec![ValidationWarning {
                message: "Consider updating".to_string(),
                path: "config.yaml".to_string(),
                recommendation: "Use newer format".to_string(),
            }],
            suggestions: vec!["Use TOML instead".to_string()],
            docs: Vec::new(),
        };

        assert!(result.valid);
        assert!(result.errors.is_empty());
        assert_eq!(result.warnings.len(), 1);
        assert_eq!(result.suggestions.len(), 1);
    }

    #[test]
    fn test_serialization_system_status() {
        let status = create_test_system_status();
        let json = serde_json::to_string(&status);
        assert!(json.is_ok());

        let deserialized: Result<SystemStatus, _> = serde_json::from_str(&json.unwrap());
        assert!(deserialized.is_ok());
    }

    #[test]
    fn test_serialization_next_action() {
        let action = NextAction {
            command: "test command".to_string(),
            description: "test description".to_string(),
            docs_link: "docs/test.md".to_string(),
            expected_outcome: "success".to_string(),
            priority: 1,
        };

        let json = serde_json::to_string(&action);
        assert!(json.is_ok());

        let deserialized: Result<NextAction, _> = serde_json::from_str(&json.unwrap());
        assert!(deserialized.is_ok());
    }

    #[test]
    fn test_serialization_diagnosis() {
        let diagnosis = Diagnosis {
            error: "test error".to_string(),
            root_cause: "test cause".to_string(),
            fixes: Vec::new(),
            related_docs: Vec::new(),
            confidence: 0.5,
        };

        let json = serde_json::to_string(&diagnosis);
        assert!(json.is_ok());

        let deserialized: Result<Diagnosis, _> = serde_json::from_str(&json.unwrap());
        assert!(deserialized.is_ok());
    }
}
