//! Framework integrity protection system
//!
//! This module provides mechanisms to ensure implementations remain compatible
//! with the framework and can receive updates safely without becoming forks.

use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};

use serde::{Deserialize, Serialize};
use thiserror::Error;

use crate::layered_override::Mergeable;

/// Framework integrity validator
#[derive(Debug)]
pub struct IntegrityValidator {
    framework_manifest: FrameworkManifest,
    implementation_root: PathBuf,
    validation_rules: Vec<ValidationRule>,
}

/// Framework manifest defining protected boundaries.
///
/// The scalar metadata (`version`, `integrity_version`, `compatibility_level`)
/// lives under a `[framework]` table in the on-disk manifest and is not
/// consumed by the validation logic, so it is defaulted here and the table is
/// ignored on load. The boundary lists default to empty, making the loader
/// robust to a manifest (e.g. a derived-layer `site_manifest.toml`) that
/// declares only some sections.
#[derive(Debug, Serialize, Deserialize)]
pub struct FrameworkManifest {
    #[serde(default)]
    pub version: String,
    #[serde(default)]
    pub integrity_version: String,
    #[serde(default)]
    pub compatibility_level: String,
    #[serde(default)]
    pub protected_paths: Vec<ProtectedPath>,
    #[serde(default)]
    pub required_traits: Vec<TraitRequirement>,
    #[serde(default)]
    pub extension_points: Vec<ExtensionPoint>,
    #[serde(default)]
    pub forbidden_patterns: Vec<ForbiddenPattern>,
    #[serde(default)]
    pub update_compatibility: CompatibilityInfo,
    #[serde(default)]
    pub validation_rules: ValidationConfig,
}

/// Protected path configuration
#[derive(Debug, Serialize, Deserialize)]
pub struct ProtectedPath {
    pub path: String,
    pub reason: String,
    pub alternatives: Vec<String>,
}

/// Trait requirement for implementations
#[derive(Debug, Serialize, Deserialize)]
pub struct TraitRequirement {
    pub trait_name: String,
    pub implementation_path: String,
    pub required_methods: Vec<String>,
    pub compatibility_version: String,
}

/// Safe extension point definition
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtensionPoint {
    pub name: String,
    pub location: String,
    pub allowed_modifications: Vec<String>,
    pub description: String,
}

/// Pattern that breaks framework compatibility
#[derive(Debug, Serialize, Deserialize)]
pub struct ForbiddenPattern {
    pub pattern: String,
    pub reason: String,
    pub suggested_alternative: String,
    pub severity: ViolationSeverity,
}

/// Update compatibility information
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct CompatibilityInfo {
    pub breaking_changes_policy: String,
    pub migration_assistance: bool,
    pub automated_migration: Vec<String>,
    pub manual_migration: Vec<String>,
}

/// Validation configuration
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ValidationConfig {
    pub max_compatibility_score: f32,
    pub critical_violations_allowed: u32,
    pub high_violations_threshold: u32,
    pub medium_violations_threshold: u32,
}

/// Validation rule definition
#[derive(Debug)]
pub struct ValidationRule {
    pub name: String,
    pub category: ViolationCategory,
    pub severity: ViolationSeverity,
    pub pattern: regex::Regex,
    pub message: String,
    pub suggested_fix: String,
}

/// Integrity validation result
#[derive(Debug, Serialize, Deserialize)]
pub struct ValidationResult {
    pub passed: bool,
    pub violations: Vec<IntegrityViolation>,
    pub warnings: Vec<IntegrityWarning>,
    pub suggestions: Vec<ImprovementSuggestion>,
    pub compatibility_score: f32,
    pub summary: ValidationSummary,
}

/// Integrity violation details
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IntegrityViolation {
    pub severity: ViolationSeverity,
    pub category: ViolationCategory,
    pub description: String,
    pub file_path: String,
    pub line_number: Option<usize>,
    pub suggested_fix: String,
    pub breaking_change: bool,
    pub auto_repairable: bool,
}

/// Integrity warning (non-blocking)
#[derive(Debug, Serialize, Deserialize)]
pub struct IntegrityWarning {
    pub category: ViolationCategory,
    pub description: String,
    pub file_path: String,
    pub suggestion: String,
}

/// Improvement suggestion
#[derive(Debug, Serialize, Deserialize)]
pub struct ImprovementSuggestion {
    pub category: String,
    pub description: String,
    pub benefit: String,
    pub implementation_guide: String,
}

/// Validation summary
#[derive(Debug, Serialize, Deserialize)]
pub struct ValidationSummary {
    pub total_files_scanned: usize,
    pub violations_by_severity: HashMap<ViolationSeverity, u32>,
    pub violations_by_category: HashMap<ViolationCategory, u32>,
    pub compatibility_score: f32,
    pub update_safety: UpdateSafety,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ViolationSeverity {
    Critical, // Breaks updates completely
    High,     // May break future updates
    Medium,   // Best practice violation
    Low,      // Style or performance issue
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ViolationCategory {
    CoreModification,       // Direct framework modification
    TraitViolation,         // Trait contract broken
    ConfigurationBypass,    // Hardcoded values bypassing config
    SecurityBreach,         // Security mechanism bypassed
    ArchitecturalViolation, // Violates framework architecture
    DeprecatedUsage,        // Uses deprecated APIs
    UnsafeCode,             // Unsafe code blocks
    ResourceAccess,         // Improper resource access patterns
}

#[derive(Debug, Serialize, Deserialize)]
pub enum UpdateSafety {
    Safe,              // Can update safely
    RequiresRepair,    // Needs violation fixes first
    RequiresMigration, // Needs manual migration
    Unsafe,            // Cannot update safely
}

impl IntegrityValidator {
    /// Create new validator from a single framework root, loading its
    /// `framework_manifest.toml`.
    pub fn new(framework_root: &Path, implementation_root: &Path) -> Result<Self, IntegrityError> {
        let manifest_path = framework_root.join("framework_manifest.toml");
        Self::from_manifests(&[manifest_path], implementation_root)
    }

    /// Create a validator from an ordered chain of manifest files (framework
    /// first, then derived layers such as a domain `site_manifest.toml`). The
    /// merged manifest unions every layer's protected paths, required traits,
    /// extension points and forbidden patterns; the framework (first) layer's
    /// compatibility policy and thresholds govern the whole chain. This is the
    /// recursive enforcement the three-level lineage relies on: a child is
    /// validated against the boundaries of every level above it at once.
    pub fn from_manifests(
        manifest_paths: &[PathBuf],
        implementation_root: &Path,
    ) -> Result<Self, IntegrityError> {
        if manifest_paths.is_empty() {
            return Err(IntegrityError::InvalidManifest(
                "no manifest paths provided".to_string(),
            ));
        }
        let mut manifests = Vec::with_capacity(manifest_paths.len());
        for path in manifest_paths {
            manifests.push(Self::load_manifest(path)?);
        }
        let framework_manifest = Self::merge_manifests(manifests);
        let validation_rules = Self::build_validation_rules(&framework_manifest)?;

        Ok(Self {
            framework_manifest,
            implementation_root: implementation_root.to_path_buf(),
            validation_rules,
        })
    }

    /// Merges an ordered manifest chain into one. List boundaries (protected
    /// paths, required traits, extension points, forbidden patterns) accumulate
    /// across all layers; the first (framework) layer's compatibility info and
    /// validation thresholds are authoritative, as the framework owns the
    /// update-compatibility contract that derived layers extend but do not
    /// redefine.
    fn merge_manifests(manifests: Vec<FrameworkManifest>) -> FrameworkManifest {
        let mut iter = manifests.into_iter();
        let mut base = iter
            .next()
            .expect("merge_manifests requires at least one manifest");
        for next in iter {
            base.protected_paths.extend(next.protected_paths);
            base.required_traits.extend(next.required_traits);
            base.extension_points.extend(next.extension_points);
            base.forbidden_patterns.extend(next.forbidden_patterns);
        }
        base
    }

    /// Load framework manifest from file
    fn load_manifest(manifest_path: &Path) -> Result<FrameworkManifest, IntegrityError> {
        if !manifest_path.exists() {
            return Err(IntegrityError::InvalidManifest(format!(
                "Framework manifest not found at {}",
                manifest_path.display()
            )));
        }

        let content = std::fs::read_to_string(manifest_path)?;
        toml::from_str(&content).map_err(|e| {
            IntegrityError::InvalidManifest(format!("Failed to parse manifest: {}", e))
        })
    }

    /// Build validation rules from manifest
    fn build_validation_rules(
        manifest: &FrameworkManifest,
    ) -> Result<Vec<ValidationRule>, IntegrityError> {
        let mut rules = Vec::new();

        // Build rules from forbidden patterns. A manifest may carry a pattern
        // the `regex` crate cannot compile (e.g. PCRE look-around, which Rust's
        // regex does not support); skip it with a warning rather than disabling
        // the whole validator. The author should rewrite such a pattern without
        // look-around, but one bad entry must not silence every other rule.
        for pattern in &manifest.forbidden_patterns {
            match regex::Regex::new(&pattern.pattern) {
                Ok(regex) => rules.push(ValidationRule {
                    name: format!("forbidden_pattern_{}", pattern.pattern),
                    category: ViolationCategory::ArchitecturalViolation,
                    severity: pattern.severity.clone(),
                    pattern: regex,
                    message: pattern.reason.clone(),
                    suggested_fix: pattern.suggested_alternative.clone(),
                }),
                Err(e) => eprintln!(
                    "integrity: skipping unsupported forbidden-pattern regex `{}`: {e}",
                    pattern.pattern
                ),
            }
        }

        // Add built-in rules
        rules.extend(Self::build_builtin_rules()?);

        Ok(rules)
    }

    /// Build built-in validation rules
    fn build_builtin_rules() -> Result<Vec<ValidationRule>, IntegrityError> {
        Ok(vec![
            // Unsafe code detection
            ValidationRule {
                name: "unsafe_code_detection".to_string(),
                category: ViolationCategory::UnsafeCode,
                severity: ViolationSeverity::High,
                pattern: regex::Regex::new(r"unsafe\s*\{")
                    .map_err(|e| IntegrityError::ParseError(e.to_string()))?,
                message: "Unsafe code block detected".to_string(),
                suggested_fix: "Use safe alternatives or request framework extension".to_string(),
            },
            // Direct import detection
            ValidationRule {
                name: "direct_core_import".to_string(),
                category: ViolationCategory::CoreModification,
                severity: ViolationSeverity::Critical,
                pattern: regex::Regex::new(r"use\s+rustelo_core::")
                    .map_err(|e| IntegrityError::ParseError(e.to_string()))?,
                message: "Direct core import bypasses framework abstractions".to_string(),
                suggested_fix: "Use public APIs and trait implementations".to_string(),
            },
            // Hardcoded route detection
            ValidationRule {
                name: "hardcoded_routes".to_string(),
                category: ViolationCategory::ConfigurationBypass,
                severity: ViolationSeverity::Critical,
                pattern: regex::Regex::new(r#""/[^"]*""#)
                    .map_err(|e| IntegrityError::ParseError(e.to_string()))?,
                message: "Potential hardcoded route detected".to_string(),
                suggested_fix: "Use route configuration in config/routes/*.toml".to_string(),
            },
        ])
    }

    /// Run full integrity validation
    pub fn validate(&self) -> Result<ValidationResult, IntegrityError> {
        let mut violations = Vec::new();
        let warnings = Vec::new();
        let mut suggestions = Vec::new();
        let mut files_scanned = 0;

        // Check protected paths
        violations.extend(self.check_protected_paths()?);

        // Validate trait implementations
        violations.extend(self.validate_trait_implementations()?);

        // Scan source files for violations
        let scan_result = self.scan_source_files()?;
        violations.extend(scan_result.violations);
        files_scanned += scan_result.files_scanned;

        // Validate configuration usage
        violations.extend(self.validate_configuration_usage()?);

        // Check extension point usage
        violations.extend(self.validate_extension_points()?);

        // Generate improvement suggestions
        suggestions.extend(self.generate_suggestions(&violations)?);

        let compatibility_score = self.calculate_compatibility_score(&violations);
        let passed = self.determine_validation_passed(&violations);
        let summary =
            self.build_validation_summary(&violations, files_scanned, compatibility_score);

        Ok(ValidationResult {
            passed,
            violations,
            warnings,
            suggestions,
            compatibility_score,
            summary,
        })
    }

    /// Focused cross-level boundary check — the gate meant for pre-commit/CI.
    /// Runs protected-path validation plus the manifest's own forbidden
    /// patterns at or above `min_severity`, scanning only `scope` when
    /// given (e.g. a commit's changed files) or the whole tree otherwise.
    /// It is deliberately scoped to the two ADR-006 enforcement axes —
    /// *don't modify/recreate an upper level's protected core* and *don't
    /// use its forbidden patterns*. It excludes the built-in heuristic
    /// rules, the quality patterns (unwrap, generic paths — clippy's and
    /// the guidelines' job), and required-trait completeness (a different
    /// axis, left to the deep `validate`). Passing
    /// `ViolationSeverity::High` keeps the architectural patterns
    /// (`pub mod core_lib`, `hardcoded_routes = [`, unsafe) and drops the rest.
    pub fn check_boundaries(
        &self,
        scope: Option<&[PathBuf]>,
        min_severity: ViolationSeverity,
    ) -> Result<ValidationResult, IntegrityError> {
        let mut violations = Vec::new();
        violations.extend(self.check_protected_paths()?);

        let min_rank = Self::severity_rank(&min_severity);
        let mut rules: Vec<(regex::Regex, &ForbiddenPattern)> = Vec::new();
        for fp in &self.framework_manifest.forbidden_patterns {
            if Self::severity_rank(&fp.severity) < min_rank {
                continue;
            }
            match regex::Regex::new(&fp.pattern) {
                Ok(re) => rules.push((re, fp)),
                Err(e) => eprintln!(
                    "integrity: skipping unsupported forbidden-pattern regex `{}`: {e}",
                    fp.pattern
                ),
            }
        }

        let files: Vec<PathBuf> = match scope {
            Some(paths) => paths
                .iter()
                .filter(|p| p.extension().is_some_and(|e| e == "rs") && p.exists())
                .cloned()
                .collect(),
            None => self.find_rust_files(&self.implementation_root)?,
        };
        let files_scanned = files.len();

        for file_path in &files {
            let content = std::fs::read_to_string(file_path)?;
            for (line_num, line) in content.lines().enumerate() {
                for (re, fp) in &rules {
                    if re.is_match(line) {
                        violations.push(IntegrityViolation {
                            severity: fp.severity.clone(),
                            category: ViolationCategory::ArchitecturalViolation,
                            description: fp.reason.clone(),
                            file_path: file_path.to_string_lossy().to_string(),
                            line_number: Some(line_num + 1),
                            suggested_fix: fp.suggested_alternative.clone(),
                            breaking_change: matches!(
                                fp.severity,
                                ViolationSeverity::Critical | ViolationSeverity::High
                            ),
                            auto_repairable: false,
                        });
                    }
                }
            }
        }

        let compatibility_score = self.calculate_compatibility_score(&violations);
        let passed = self.determine_validation_passed(&violations);
        let summary =
            self.build_validation_summary(&violations, files_scanned, compatibility_score);

        Ok(ValidationResult {
            passed,
            violations,
            warnings: Vec::new(),
            suggestions: Vec::new(),
            compatibility_score,
            summary,
        })
    }

    /// Severity ordering for threshold filtering (higher = more severe).
    fn severity_rank(s: &ViolationSeverity) -> u8 {
        match s {
            ViolationSeverity::Critical => 4,
            ViolationSeverity::High => 3,
            ViolationSeverity::Medium => 2,
            ViolationSeverity::Low => 1,
        }
    }

    /// Check if protected framework paths are modified
    fn check_protected_paths(&self) -> Result<Vec<IntegrityViolation>, IntegrityError> {
        let mut violations = Vec::new();

        for protected in &self.framework_manifest.protected_paths {
            let full_path = self.implementation_root.join(&protected.path);

            // A protected path is only a *modification* when the implementation
            // holds real, own content there. In the sibling-crate model an impl
            // path-deps the framework and never copies its tree, so a colliding
            // path is normally a symlink/reference into the framework checkout
            // (e.g. templates/shared/htmx → ../rustelo/templates/shared/htmx) or
            // a directory of pure references — neither recreates framework
            // source. Only real, non-symlinked content can.
            if full_path.exists()
                && self.has_real_content(&full_path)?
                && !self.is_authorized_override(&full_path)?
            {
                violations.push(IntegrityViolation {
                    severity: ViolationSeverity::Critical,
                    category: ViolationCategory::CoreModification,
                    description: format!(
                        "Unauthorized modification of protected framework path: {}",
                        protected.path
                    ),
                    file_path: full_path.to_string_lossy().to_string(),
                    line_number: None,
                    suggested_fix: format!(
                        "Remove modifications to {} and use appropriate extension points: {}",
                        protected.path,
                        protected.alternatives.join(", ")
                    ),
                    breaking_change: true,
                    auto_repairable: false,
                });
            }
        }

        Ok(violations)
    }

    /// Whether a path holds real, implementation-owned content as opposed to a
    /// mere reference. A symlink is a reference, never a modification of
    /// framework source — the canonical way an implementation consumes vendored
    /// framework assets is to symlink into the framework checkout. A directory
    /// counts only if it transitively contains a regular, non-symlinked file; a
    /// directory of pure symlinks (or an empty one) is a reference, not a
    /// recreation.
    fn has_real_content(&self, path: &Path) -> Result<bool, IntegrityError> {
        let ft = std::fs::symlink_metadata(path)?.file_type();
        if ft.is_symlink() {
            return Ok(false);
        }
        if ft.is_file() {
            return Ok(true);
        }
        if ft.is_dir() {
            for entry in std::fs::read_dir(path)? {
                if self.has_real_content(&entry?.path())? {
                    return Ok(true);
                }
            }
        }
        Ok(false)
    }

    /// Check if a path modification is an authorized override
    fn is_authorized_override(&self, path: &Path) -> Result<bool, IntegrityError> {
        // Check if path is within an authorized extension point
        for extension_point in &self.framework_manifest.extension_points {
            let extension_path = self.implementation_root.join(&extension_point.location);
            if path.starts_with(&extension_path) {
                return Ok(true);
            }
        }

        // Check if it's in a recognized override location (config/local/, etc.)
        let known_override_paths = [
            "config/local/",
            "src/components/custom/",
            "src/content/processors/",
        ];

        for override_path in &known_override_paths {
            let full_override_path = self.implementation_root.join(override_path);
            if path.starts_with(&full_override_path) {
                return Ok(true);
            }
        }

        Ok(false)
    }

    /// Validate trait implementation compliance
    fn validate_trait_implementations(&self) -> Result<Vec<IntegrityViolation>, IntegrityError> {
        let mut violations = Vec::new();

        for trait_req in &self.framework_manifest.required_traits {
            let impl_path = self
                .implementation_root
                .join(&trait_req.implementation_path);

            if !impl_path.exists() {
                violations.push(IntegrityViolation {
                    severity: ViolationSeverity::High,
                    category: ViolationCategory::TraitViolation,
                    description: format!(
                        "Missing required trait implementation: {}",
                        trait_req.trait_name
                    ),
                    file_path: impl_path.to_string_lossy().to_string(),
                    line_number: None,
                    suggested_fix: format!(
                        "Implement required trait {} at {}",
                        trait_req.trait_name, trait_req.implementation_path
                    ),
                    breaking_change: true,
                    auto_repairable: false,
                });
                continue;
            }

            // Validate trait implementation completeness
            let impl_content = std::fs::read_to_string(&impl_path)?;
            violations.extend(self.validate_trait_methods(&impl_content, trait_req, &impl_path)?);
        }

        Ok(violations)
    }

    /// Validate trait methods implementation
    fn validate_trait_methods(
        &self,
        content: &str,
        trait_req: &TraitRequirement,
        impl_path: &Path,
    ) -> Result<Vec<IntegrityViolation>, IntegrityError> {
        let mut violations = Vec::new();

        for required_method in &trait_req.required_methods {
            let method_pattern = format!(r"fn\s+{}\s*\(", regex::escape(required_method));
            let regex = regex::Regex::new(&method_pattern)
                .map_err(|e| IntegrityError::ParseError(e.to_string()))?;

            if !regex.is_match(content) {
                violations.push(IntegrityViolation {
                    severity: ViolationSeverity::High,
                    category: ViolationCategory::TraitViolation,
                    description: format!(
                        "Missing required method '{}' in trait '{}'",
                        required_method, trait_req.trait_name
                    ),
                    file_path: impl_path.to_string_lossy().to_string(),
                    line_number: None,
                    suggested_fix: format!(
                        "Implement method '{}' as required by trait '{}'",
                        required_method, trait_req.trait_name
                    ),
                    breaking_change: true,
                    auto_repairable: false,
                });
            }
        }

        Ok(violations)
    }

    /// Scan source files for violations
    fn scan_source_files(&self) -> Result<SourceScanResult, IntegrityError> {
        let mut violations = Vec::new();
        let mut files_scanned = 0;

        let rust_files = self.find_rust_files(&self.implementation_root)?;

        for file_path in rust_files {
            let content = std::fs::read_to_string(&file_path)?;
            files_scanned += 1;

            for (line_num, line) in content.lines().enumerate() {
                for rule in &self.validation_rules {
                    if rule.pattern.is_match(line) {
                        violations.push(IntegrityViolation {
                            severity: rule.severity.clone(),
                            category: rule.category.clone(),
                            description: rule.message.clone(),
                            file_path: file_path.to_string_lossy().to_string(),
                            line_number: Some(line_num + 1),
                            suggested_fix: rule.suggested_fix.clone(),
                            breaking_change: matches!(
                                rule.severity,
                                ViolationSeverity::Critical | ViolationSeverity::High
                            ),
                            auto_repairable: matches!(
                                rule.category,
                                ViolationCategory::DeprecatedUsage
                                    | ViolationCategory::ConfigurationBypass
                            ),
                        });
                    }
                }
            }
        }

        Ok(SourceScanResult {
            violations,
            files_scanned,
        })
    }

    /// Find all Rust source files in the implementation
    fn find_rust_files(&self, root: &Path) -> Result<Vec<PathBuf>, IntegrityError> {
        let mut rust_files = Vec::new();

        fn walk_dir(dir: &Path, files: &mut Vec<PathBuf>) -> Result<(), IntegrityError> {
            if dir.is_dir() {
                for entry in std::fs::read_dir(dir)? {
                    let entry = entry?;
                    let path = entry.path();

                    if path.is_dir() {
                        // Skip target directory and other build artifacts
                        if let Some(dir_name) = path.file_name() {
                            if dir_name == "target" || dir_name == "node_modules" {
                                continue;
                            }
                        }
                        walk_dir(&path, files)?;
                    } else if let Some(ext) = path.extension() {
                        if ext == "rs" {
                            files.push(path);
                        }
                    }
                }
            }
            Ok(())
        }

        walk_dir(root, &mut rust_files)?;
        Ok(rust_files)
    }

    /// Validate configuration usage patterns
    fn validate_configuration_usage(&self) -> Result<Vec<IntegrityViolation>, IntegrityError> {
        let violations = Vec::new();

        // Check for hardcoded values that should be configurable
        let config_files = self.find_config_files()?;

        for config_file in config_files {
            let _content = std::fs::read_to_string(&config_file)?;
            // Check for patterns that indicate configuration bypass
            // This would include more sophisticated analysis in a real
            // implementation
        }

        Ok(violations)
    }

    /// Find configuration files
    fn find_config_files(&self) -> Result<Vec<PathBuf>, IntegrityError> {
        let mut config_files = Vec::new();
        let config_dir = self.implementation_root.join("config");

        if config_dir.exists() {
            // Recursively find TOML and other config files
            self.find_files_with_extensions(
                &config_dir,
                &["toml", "json", "yaml", "yml"],
                &mut config_files,
            )?;
        }

        Ok(config_files)
    }

    /// Find files with specific extensions
    fn find_files_with_extensions(
        &self,
        dir: &Path,
        extensions: &[&str],
        files: &mut Vec<PathBuf>,
    ) -> Result<(), IntegrityError> {
        if dir.is_dir() {
            for entry in std::fs::read_dir(dir)? {
                let entry = entry?;
                let path = entry.path();

                if path.is_dir() {
                    self.find_files_with_extensions(&path, extensions, files)?;
                } else if let Some(ext) = path.extension() {
                    if extensions.iter().any(|&e| ext == e) {
                        files.push(path);
                    }
                }
            }
        }
        Ok(())
    }

    /// Validate extension point usage
    fn validate_extension_points(&self) -> Result<Vec<IntegrityViolation>, IntegrityError> {
        let mut violations = Vec::new();

        for extension_point in &self.framework_manifest.extension_points {
            let extension_path = self.implementation_root.join(&extension_point.location);

            if extension_path.exists() {
                // Validate that modifications are within allowed types
                violations.extend(
                    self.validate_extension_point_modifications(&extension_path, extension_point)?,
                );
            }
        }

        Ok(violations)
    }

    /// Validate specific extension point modifications
    fn validate_extension_point_modifications(
        &self,
        _path: &Path,
        _extension_point: &ExtensionPoint,
    ) -> Result<Vec<IntegrityViolation>, IntegrityError> {
        let violations = Vec::new();

        // This would include more sophisticated validation based on
        // the allowed_modifications field and the specific extension point type

        Ok(violations)
    }

    /// Generate improvement suggestions
    fn generate_suggestions(
        &self,
        violations: &[IntegrityViolation],
    ) -> Result<Vec<ImprovementSuggestion>, IntegrityError> {
        let mut suggestions = Vec::new();

        // Analyze violations and suggest improvements
        let violation_counts = self.count_violations_by_category(violations);

        if violation_counts
            .get(&ViolationCategory::ConfigurationBypass)
            .unwrap_or(&0)
            > &0
        {
            suggestions.push(ImprovementSuggestion {
                category: "Configuration".to_string(),
                description: "Move hardcoded values to configuration files".to_string(),
                benefit: "Easier customization and better update compatibility".to_string(),
                implementation_guide: "Create TOML files in config/ directory and use framework \
                                       config APIs"
                    .to_string(),
            });
        }

        if violation_counts
            .get(&ViolationCategory::UnsafeCode)
            .unwrap_or(&0)
            > &0
        {
            suggestions.push(ImprovementSuggestion {
                category: "Safety".to_string(),
                description: "Eliminate unsafe code blocks".to_string(),
                benefit: "Better memory safety and framework compatibility".to_string(),
                implementation_guide: "Use framework-provided safe abstractions or request new \
                                       APIs"
                    .to_string(),
            });
        }

        Ok(suggestions)
    }

    /// Count violations by category
    fn count_violations_by_category(
        &self,
        violations: &[IntegrityViolation],
    ) -> HashMap<ViolationCategory, u32> {
        let mut counts = HashMap::new();

        for violation in violations {
            *counts.entry(violation.category.clone()).or_insert(0) += 1;
        }

        counts
    }

    /// Calculate compatibility score (0.0 = incompatible, 1.0 = fully
    /// compatible)
    fn calculate_compatibility_score(&self, violations: &[IntegrityViolation]) -> f32 {
        if violations.is_empty() {
            return 1.0;
        }

        let total_severity_score: f32 = violations
            .iter()
            .map(|v| match v.severity {
                ViolationSeverity::Critical => 10.0,
                ViolationSeverity::High => 5.0,
                ViolationSeverity::Medium => 2.0,
                ViolationSeverity::Low => 0.5,
            })
            .sum();

        let max_possible_score = 100.0; // Arbitrary baseline
        (max_possible_score - total_severity_score).max(0.0) / max_possible_score
    }

    /// Determine if validation passed based on thresholds
    fn determine_validation_passed(&self, violations: &[IntegrityViolation]) -> bool {
        let critical_count = violations
            .iter()
            .filter(|v| matches!(v.severity, ViolationSeverity::Critical))
            .count() as u32;

        let high_count = violations
            .iter()
            .filter(|v| matches!(v.severity, ViolationSeverity::High))
            .count() as u32;

        let medium_count = violations
            .iter()
            .filter(|v| matches!(v.severity, ViolationSeverity::Medium))
            .count() as u32;

        critical_count
            <= self
                .framework_manifest
                .validation_rules
                .critical_violations_allowed
            && high_count
                <= self
                    .framework_manifest
                    .validation_rules
                    .high_violations_threshold
            && medium_count
                <= self
                    .framework_manifest
                    .validation_rules
                    .medium_violations_threshold
    }

    /// Build validation summary
    fn build_validation_summary(
        &self,
        violations: &[IntegrityViolation],
        files_scanned: usize,
        compatibility_score: f32,
    ) -> ValidationSummary {
        let violations_by_severity = violations.iter().fold(HashMap::new(), |mut acc, v| {
            *acc.entry(v.severity.clone()).or_insert(0) += 1;
            acc
        });

        let violations_by_category = violations.iter().fold(HashMap::new(), |mut acc, v| {
            *acc.entry(v.category.clone()).or_insert(0) += 1;
            acc
        });

        let update_safety = if compatibility_score
            >= self
                .framework_manifest
                .validation_rules
                .max_compatibility_score
        {
            UpdateSafety::Safe
        } else if violations.iter().any(|v| v.auto_repairable) {
            UpdateSafety::RequiresRepair
        } else if violations
            .iter()
            .any(|v| matches!(v.severity, ViolationSeverity::Critical))
        {
            UpdateSafety::Unsafe
        } else {
            UpdateSafety::RequiresMigration
        };

        ValidationSummary {
            total_files_scanned: files_scanned,
            violations_by_severity,
            violations_by_category,
            compatibility_score,
            update_safety,
        }
    }
}

/// Result of source file scanning
struct SourceScanResult {
    violations: Vec<IntegrityViolation>,
    files_scanned: usize,
}

/// Integrity error types
#[derive(Debug, Error)]
pub enum IntegrityError {
    #[error("Framework manifest not found or invalid: {0}")]
    InvalidManifest(String),

    #[error("IO error during validation: {0}")]
    IoError(#[from] std::io::Error),

    #[error("Parsing error: {0}")]
    ParseError(String),

    #[error("Configuration error: {0}")]
    ConfigurationError(String),

    #[error("Validation rule error: {0}")]
    ValidationRuleError(String),
}

/// Auto-repair capability for common violations
impl IntegrityValidator {
    /// Attempt to automatically fix violations where possible
    pub fn auto_repair(
        &self,
        violations: &[IntegrityViolation],
    ) -> Result<RepairResult, IntegrityError> {
        let mut repaired = Vec::new();
        let mut failed = Vec::new();

        for violation in violations {
            if violation.auto_repairable {
                match self.attempt_repair(violation) {
                    Ok(()) => repaired.push(violation.clone()),
                    Err(e) => failed.push((violation.clone(), e)),
                }
            } else {
                failed.push((
                    violation.clone(),
                    IntegrityError::ConfigurationError(
                        "Manual repair required for this violation type".to_string(),
                    ),
                ));
            }
        }

        Ok(RepairResult { repaired, failed })
    }

    /// Attempt to repair a specific violation
    fn attempt_repair(&self, violation: &IntegrityViolation) -> Result<(), IntegrityError> {
        match violation.category {
            ViolationCategory::ConfigurationBypass => self.repair_configuration_bypass(violation),
            ViolationCategory::DeprecatedUsage => self.repair_deprecated_usage(violation),
            _ => Err(IntegrityError::ConfigurationError(
                "This violation type cannot be automatically repaired".to_string(),
            )),
        }
    }

    /// Repair configuration bypass violations
    fn repair_configuration_bypass(
        &self,
        _violation: &IntegrityViolation,
    ) -> Result<(), IntegrityError> {
        // Implementation would include specific repair logic for configuration bypasses
        // This is a placeholder for the actual repair logic
        Ok(())
    }

    /// Repair deprecated usage violations
    fn repair_deprecated_usage(
        &self,
        _violation: &IntegrityViolation,
    ) -> Result<(), IntegrityError> {
        // Implementation would include specific repair logic for deprecated API usage
        // This is a placeholder for the actual repair logic
        Ok(())
    }
}

/// Auto-repair result
#[derive(Debug)]
pub struct RepairResult {
    pub repaired: Vec<IntegrityViolation>,
    pub failed: Vec<(IntegrityViolation, IntegrityError)>,
}

impl Default for FrameworkManifest {
    fn default() -> Self {
        Self {
            version: "0.1.0".to_string(),
            integrity_version: "1.0".to_string(),
            compatibility_level: "stable".to_string(),
            protected_paths: Vec::new(),
            required_traits: Vec::new(),
            extension_points: Vec::new(),
            forbidden_patterns: Vec::new(),
            update_compatibility: CompatibilityInfo {
                breaking_changes_policy: "semantic_versioning".to_string(),
                migration_assistance: true,
                automated_migration: Vec::new(),
                manual_migration: Vec::new(),
            },
            validation_rules: ValidationConfig {
                max_compatibility_score: 0.8,
                critical_violations_allowed: 0,
                high_violations_threshold: 3,
                medium_violations_threshold: 10,
            },
        }
    }
}
