use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum SeverityLevel {
    Critical,
    High,
    Medium,
    Low,
    Info,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum VulnerabilityStatus {
    Open,
    Acknowledged,
    InProgress,
    Resolved,
    FalsePositive,
    Accepted,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ScanType {
    DependencyCheck,
    ContainerScan,
    CodeAnalysis,
    SecretDetection,
    ConfigurationAudit,
    NetworkScan,
    ComplianceCheck,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Vulnerability {
    pub id: Uuid,
    pub external_id: Option<String>,
    pub cve_id: Option<String>,
    pub cwe_id: Option<String>,
    pub title: String,
    pub description: String,
    pub severity: SeverityLevel,
    pub cvss_score: Option<f32>,
    pub cvss_vector: Option<String>,
    pub status: VulnerabilityStatus,
    pub scan_type: ScanType,
    pub affected_component: String,
    pub affected_version: Option<String>,
    pub fixed_version: Option<String>,
    pub file_path: Option<String>,
    pub line_number: Option<u32>,
    pub remediation: Option<String>,
    pub references: Vec<String>,
    pub tags: Vec<String>,
    pub first_detected: DateTime<Utc>,
    pub last_seen: DateTime<Utc>,
    pub resolved_at: Option<DateTime<Utc>>,
    pub resolved_by: Option<Uuid>,
    pub assigned_to: Option<Uuid>,
    pub notes: Vec<VulnerabilityNote>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VulnerabilityNote {
    pub id: Uuid,
    pub content: String,
    pub author_id: Uuid,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScanResult {
    pub id: Uuid,
    pub scan_type: ScanType,
    pub started_at: DateTime<Utc>,
    pub completed_at: Option<DateTime<Utc>>,
    pub status: ScanStatus,
    pub vulnerabilities_found: u32,
    pub critical_count: u32,
    pub high_count: u32,
    pub medium_count: u32,
    pub low_count: u32,
    pub info_count: u32,
    pub scanned_items: u32,
    pub scan_duration_ms: Option<u64>,
    pub scanner_version: String,
    pub error_message: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ScanStatus {
    Pending,
    Running,
    Completed,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScanConfiguration {
    pub scan_types: Vec<ScanType>,
    pub schedule: ScanSchedule,
    pub severity_threshold: SeverityLevel,
    pub fail_on_severity: Option<SeverityLevel>,
    pub ignore_patterns: Vec<String>,
    pub include_dev_dependencies: bool,
    pub max_depth: Option<u32>,
    pub timeout_seconds: u32,
    pub notify_on_completion: bool,
    pub notification_channels: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScanSchedule {
    pub enabled: bool,
    pub cron_expression: Option<String>,
    pub run_on_commit: bool,
    pub run_on_pr: bool,
    pub run_daily: bool,
    pub run_weekly: bool,
}

impl Default for ScanConfiguration {
    fn default() -> Self {
        Self {
            scan_types: vec![
                ScanType::DependencyCheck,
                ScanType::SecretDetection,
                ScanType::ConfigurationAudit,
            ],
            schedule: ScanSchedule {
                enabled: true,
                cron_expression: Some("0 2 * * *".to_string()),
                run_on_commit: false,
                run_on_pr: true,
                run_daily: true,
                run_weekly: false,
            },
            severity_threshold: SeverityLevel::Low,
            fail_on_severity: Some(SeverityLevel::Critical),
            ignore_patterns: Vec::new(),
            include_dev_dependencies: false,
            max_depth: None,
            timeout_seconds: 3600,
            notify_on_completion: true,
            notification_channels: vec!["email".to_string(), "slack".to_string()],
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DependencyInfo {
    pub name: String,
    pub version: String,
    pub ecosystem: String,
    pub direct: bool,
    pub license: Option<String>,
    pub vulnerabilities: Vec<Uuid>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityPolicy {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub rules: Vec<PolicyRule>,
    pub enforcement: PolicyEnforcement,
    pub enabled: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyRule {
    pub id: Uuid,
    pub rule_type: PolicyRuleType,
    pub condition: String,
    pub action: PolicyAction,
    pub severity_override: Option<SeverityLevel>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PolicyRuleType {
    BlockSeverity,
    RequireReview,
    AllowWithException,
    BlockLicense,
    BlockPackage,
    RequireFix,
    AgeLimit,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PolicyAction {
    Block,
    Warn,
    RequireApproval,
    LogOnly,
    Notify,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PolicyEnforcement {
    Strict,
    Advisory,
    Disabled,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VulnerabilityReport {
    pub id: Uuid,
    pub generated_at: DateTime<Utc>,
    pub report_type: ReportType,
    pub period_start: DateTime<Utc>,
    pub period_end: DateTime<Utc>,
    pub summary: ReportSummary,
    pub vulnerabilities: Vec<Vulnerability>,
    pub trends: VulnerabilityTrends,
    pub recommendations: Vec<Recommendation>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ReportType {
    Summary,
    Detailed,
    Executive,
    Compliance,
    Audit,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportSummary {
    pub total_vulnerabilities: u32,
    pub new_vulnerabilities: u32,
    pub resolved_vulnerabilities: u32,
    pub open_vulnerabilities: u32,
    pub by_severity: HashMap<String, u32>,
    pub by_status: HashMap<String, u32>,
    pub by_type: HashMap<String, u32>,
    pub mean_time_to_remediate_days: Option<f32>,
    pub compliance_score: f32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VulnerabilityTrends {
    pub total_over_time: Vec<TrendDataPoint>,
    pub by_severity_over_time: HashMap<String, Vec<TrendDataPoint>>,
    pub mttr_over_time: Vec<TrendDataPoint>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrendDataPoint {
    pub timestamp: DateTime<Utc>,
    pub value: f32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Recommendation {
    pub priority: u32,
    pub title: String,
    pub description: String,
    pub affected_count: u32,
    pub estimated_effort: String,
    pub action_items: Vec<String>,
}

pub struct VulnerabilityScannerService {
    vulnerabilities: Arc<RwLock<HashMap<Uuid, Vulnerability>>>,
    scan_results: Arc<RwLock<Vec<ScanResult>>>,
    dependencies: Arc<RwLock<Vec<DependencyInfo>>>,
    policies: Arc<RwLock<HashMap<Uuid, SecurityPolicy>>>,
    configuration: Arc<RwLock<ScanConfiguration>>,
}

impl VulnerabilityScannerService {
    pub fn new() -> Self {
        Self {
            vulnerabilities: Arc::new(RwLock::new(HashMap::new())),
            scan_results: Arc::new(RwLock::new(Vec::new())),
            dependencies: Arc::new(RwLock::new(Vec::new())),
            policies: Arc::new(RwLock::new(HashMap::new())),
            configuration: Arc::new(RwLock::new(ScanConfiguration::default())),
        }
    }

    pub async fn run_scan(&self, scan_types: Vec<ScanType>) -> Result<ScanResult, ScanError> {
        let scan_id = Uuid::new_v4();
        let started_at = Utc::now();

        let mut result = ScanResult {
            id: scan_id,
            scan_type: scan_types.first().cloned().unwrap_or(ScanType::DependencyCheck),
            started_at,
            completed_at: None,
            status: ScanStatus::Running,
            vulnerabilities_found: 0,
            critical_count: 0,
            high_count: 0,
            medium_count: 0,
            low_count: 0,
            info_count: 0,
            scanned_items: 0,
            scan_duration_ms: None,
            scanner_version: "1.0.0".to_string(),
            error_message: None,
        };

        let mut all_vulnerabilities = Vec::new();

        for scan_type in scan_types {
            match scan_type {
                ScanType::DependencyCheck => {
                    let vulns = self.scan_dependencies().await?;
                    all_vulnerabilities.extend(vulns);
                }
                ScanType::SecretDetection => {
                    let vulns = self.scan_for_secrets().await?;
                    all_vulnerabilities.extend(vulns);
                }
                ScanType::ConfigurationAudit => {
                    let vulns = self.audit_configuration().await?;
                    all_vulnerabilities.extend(vulns);
                }
                ScanType::ContainerScan => {
                    let vulns = self.scan_containers().await?;
                    all_vulnerabilities.extend(vulns);
                }
                ScanType::CodeAnalysis => {
                    let vulns = self.analyze_code().await?;
                    all_vulnerabilities.extend(vulns);
                }
                ScanType::NetworkScan => {
                    let vulns = self.scan_network().await?;
                    all_vulnerabilities.extend(vulns);
                }
                ScanType::ComplianceCheck => {
                    let vulns = self.check_compliance().await?;
                    all_vulnerabilities.extend(vulns);
                }
            }
        }

        for vuln in &all_vulnerabilities {
            match vuln.severity {
                SeverityLevel::Critical => result.critical_count += 1,
                SeverityLevel::High => result.high_count += 1,
                SeverityLevel::Medium => result.medium_count += 1,
                SeverityLevel::Low => result.low_count += 1,
                SeverityLevel::Info => result.info_count += 1,
            }
        }

        result.vulnerabilities_found = all_vulnerabilities.len() as u32;
        result.completed_at = Some(Utc::now());
        result.status = ScanStatus::Completed;
        result.scan_duration_ms = Some(
            (Utc::now() - started_at).num_milliseconds() as u64
        );

        let mut vulns = self.vulnerabilities.write().await;
        for vuln in all_vulnerabilities {
            vulns.insert(vuln.id, vuln);
        }

        let mut results = self.scan_results.write().await;
        results.push(result.clone());

        Ok(result)
    }

    async fn scan_dependencies(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let vulnerabilities = Vec::new();

        let sample_deps: Vec<(&str, &str, Option<&str>)> = vec![
            ("tokio", "1.40.0", None),
            ("serde", "1.0.210", None),
            ("axum", "0.7.5", None),
            ("diesel", "2.1.0", None),
        ];

        let mut deps = self.dependencies.write().await;
        deps.clear();

        for (name, version, _vuln) in sample_deps {
            deps.push(DependencyInfo {
                name: name.to_string(),
                version: version.to_string(),
                ecosystem: "cargo".to_string(),
                direct: true,
                license: Some("MIT".to_string()),
                vulnerabilities: Vec::new(),
            });
        }

        Ok(vulnerabilities)
    }

    async fn scan_for_secrets(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let mut vulnerabilities = Vec::new();
        let now = Utc::now();

let secret_patterns = vec![
("API Key Pattern", r#"(?i)(api[_-]?key|apikey)\s*[:=]\s*['"]?[\w-]{20,}"#, "CWE-798"),
("AWS Access Key ", r"AKIA[0-9A-Z]{16}", "CWE-798"),
("Private Key ", r"-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----", "CWE-321"),
("JWT Token ", r#"eyJ[A-Za-z0-9-]+.[A-Za-z0-9-]+.[A-Za-z0-9-_.+/]*"#, "CWE-522"),
("Database URL ", r#"(?i)(postgres|mysql|mongodb)://[^\s]+:[^\s]+@"#, "CWE-798"),
];

        for (name, pattern, cwe) in secret_patterns {
            let regex_result = regex::Regex::new(pattern);
            if regex_result.is_ok() {
                vulnerabilities.push(Vulnerability {
                    id: Uuid::new_v4(),
                    external_id: None,
                    cve_id: None,
                    cwe_id: Some(cwe.to_string()),
                    title: format!("Secret Detection: {name}"),
                    description: format!("Pattern check configured for: {name}. Run full scan to detect occurrences."),
                    severity: SeverityLevel::Info,
                    cvss_score: None,
                    cvss_vector: None,
                    status: VulnerabilityStatus::Open,
                    scan_type: ScanType::SecretDetection,
                    affected_component: "Codebase".to_string(),
                    affected_version: None,
                    fixed_version: None,
                    file_path: None,
                    line_number: None,
                    remediation: Some("Remove hardcoded secrets and use environment variables or secret management systems".to_string()),
                    references: vec!["https://cwe.mitre.org/data/definitions/798.html".to_string()],
                    tags: vec!["secrets".to_string(), "hardcoded-credentials".to_string()],
                    first_detected: now,
                    last_seen: now,
                    resolved_at: None,
                    resolved_by: None,
                    assigned_to: None,
                    notes: Vec::new(),
                });
            }
        }

        Ok(vulnerabilities)
    }

    async fn audit_configuration(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let mut vulnerabilities = Vec::new();

        let config_checks = vec![
            ("TLS 1.2+ Required", true, SeverityLevel::High),
            ("HSTS Enabled", true, SeverityLevel::Medium),
            ("CORS Properly Configured", true, SeverityLevel::Medium),
            ("Rate Limiting Enabled", true, SeverityLevel::Low),
            ("Security Headers Present", true, SeverityLevel::Medium),
        ];

        for (check_name, passes, severity) in config_checks {
            if !passes {
                vulnerabilities.push(Vulnerability {
                    id: Uuid::new_v4(),
                    external_id: None,
                    cve_id: None,
                    cwe_id: Some("CWE-16".to_string()),
                    title: format!("Configuration Issue: {check_name}"),
                    description: format!("Security configuration check failed: {check_name}"),
                    severity,
                    cvss_score: None,
                    cvss_vector: None,
                    status: VulnerabilityStatus::Open,
                    scan_type: ScanType::ConfigurationAudit,
                    affected_component: "Configuration".to_string(),
                    affected_version: None,
                    fixed_version: None,
                    file_path: None,
                    line_number: None,
                    remediation: Some(format!("Enable or properly configure: {check_name}")),
                    references: Vec::new(),
                    tags: vec!["configuration".to_string()],
                    first_detected: Utc::now(),
                    last_seen: Utc::now(),
                    resolved_at: None,
                    resolved_by: None,
                    assigned_to: None,
                    notes: Vec::new(),
                });
            }
        }

        Ok(vulnerabilities)
    }

    async fn scan_containers(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let mut vulnerabilities = Vec::new();
        let now = Utc::now();

        let container_checks = vec![
            ("Base Image", "alpine:latest", SeverityLevel::Low, "Use specific version tags instead of 'latest'"),
            ("Root User", "USER root", SeverityLevel::High, "Run containers as non-root user"),
            ("Privileged Mode", "--privileged", SeverityLevel::Critical, "Avoid running containers in privileged mode"),
            ("Host Network", "--network=host", SeverityLevel::Medium, "Use bridge or custom networks instead of host"),
            ("Sensitive Mounts", "/etc/passwd", SeverityLevel::High, "Avoid mounting sensitive host paths"),
        ];

        for (check_name, indicator, severity, remediation) in container_checks {
            vulnerabilities.push(Vulnerability {
                id: Uuid::new_v4(),
                external_id: None,
                cve_id: None,
                cwe_id: Some("CWE-250".to_string()),
                title: format!("Container Security: {check_name}"),
                description: format!("Container configuration check for: {indicator}"),
                severity,
                cvss_score: None,
                cvss_vector: None,
                status: VulnerabilityStatus::Open,
                scan_type: ScanType::ContainerScan,
                affected_component: "Container Configuration".to_string(),
                affected_version: None,
                fixed_version: None,
                file_path: Some("Dockerfile".to_string()),
                line_number: None,
                remediation: Some(remediation.to_string()),
                references: vec!["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/".to_string()],
                tags: vec!["container".to_string(), "docker".to_string()],
                first_detected: now,
                last_seen: now,
                resolved_at: None,
                resolved_by: None,
                assigned_to: None,
                notes: Vec::new(),
            });
        }

        Ok(vulnerabilities)
    }

    async fn analyze_code(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let mut vulnerabilities = Vec::new();
        let now = Utc::now();

        let code_patterns = vec![
            ("SQL Injection", "CWE-89", SeverityLevel::Critical, "Use parameterized queries or prepared statements"),
            ("XSS Vulnerability", "CWE-79", SeverityLevel::High, "Sanitize and encode user input before rendering"),
            ("Command Injection", "CWE-78", SeverityLevel::Critical, "Validate and sanitize all user input before command execution"),
            ("Path Traversal", "CWE-22", SeverityLevel::High, "Validate file paths and use allowlists"),
            ("Insecure Deserialization", "CWE-502", SeverityLevel::High, "Validate serialized data and use safe deserialization methods"),
            ("Buffer Overflow", "CWE-120", SeverityLevel::Critical, "Use memory-safe functions and bounds checking"),
            ("Integer Overflow", "CWE-190", SeverityLevel::Medium, "Validate integer operations and use checked arithmetic"),
            ("Use After Free", "CWE-416", SeverityLevel::Critical, "Use memory-safe languages or careful pointer management"),
        ];

        for (vuln_name, cwe, severity, remediation) in code_patterns {
            vulnerabilities.push(Vulnerability {
                id: Uuid::new_v4(),
                external_id: None,
                cve_id: None,
                cwe_id: Some(cwe.to_string()),
                title: format!("Code Analysis: {vuln_name}"),
                description: format!("Static analysis check for {vuln_name} patterns"),
                severity,
                cvss_score: None,
                cvss_vector: None,
                status: VulnerabilityStatus::Open,
                scan_type: ScanType::CodeAnalysis,
                affected_component: "Source Code".to_string(),
                affected_version: None,
                fixed_version: None,
                file_path: None,
                line_number: None,
                remediation: Some(remediation.to_string()),
                references: vec![format!("https://cwe.mitre.org/data/definitions/{}.html", cwe.replace("CWE-", ""))],
                tags: vec!["sast".to_string(), "code-analysis".to_string()],
                first_detected: now,
                last_seen: now,
                resolved_at: None,
                resolved_by: None,
                assigned_to: None,
                notes: Vec::new(),
            });
        }

        Ok(vulnerabilities)
    }

    async fn scan_network(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let mut vulnerabilities = Vec::new();
        let now = Utc::now();

        let network_checks = vec![
            ("Open Ports", "CWE-200", SeverityLevel::Medium, "Close unnecessary ports and use firewall rules", vec!["22", "80", "443", "5432", "6379"]),
            ("SSL/TLS Version", "CWE-326", SeverityLevel::High, "Use TLS 1.2 or higher", vec!["TLS 1.0", "TLS 1.1", "SSLv3"]),
            ("Weak Ciphers", "CWE-327", SeverityLevel::Medium, "Use strong cipher suites", vec!["DES", "RC4", "MD5"]),
            ("Missing HTTPS", "CWE-319", SeverityLevel::High, "Enable HTTPS for all endpoints", vec!["http://"]),
            ("DNS Security", "CWE-350", SeverityLevel::Medium, "Implement DNSSEC", vec!["unsigned zone"]),
        ];

        for (check_name, cwe, severity, remediation, indicators) in network_checks {
            vulnerabilities.push(Vulnerability {
                id: Uuid::new_v4(),
                external_id: None,
                cve_id: None,
                cwe_id: Some(cwe.to_string()),
                title: format!("Network Security: {check_name}"),
                description: format!("Network scan check for: {}", indicators.join(", ")),
                severity,
                cvss_score: None,
                cvss_vector: None,
                status: VulnerabilityStatus::Open,
                scan_type: ScanType::NetworkScan,
                affected_component: "Network Configuration".to_string(),
                affected_version: None,
                fixed_version: None,
                file_path: None,
                line_number: None,
                remediation: Some(remediation.to_string()),
                references: vec![format!("https://cwe.mitre.org/data/definitions/{}.html", cwe.replace("CWE-", ""))],
                tags: vec!["network".to_string(), "infrastructure".to_string()],
                first_detected: now,
                last_seen: now,
                resolved_at: None,
                resolved_by: None,
                assigned_to: None,
                notes: Vec::new(),
            });
        }

        Ok(vulnerabilities)
    }

    async fn check_compliance(&self) -> Result<Vec<Vulnerability>, ScanError> {
        let mut vulnerabilities = Vec::new();
        let now = Utc::now();

        let compliance_checks = vec![
            ("GDPR - Data Encryption", "CWE-311", SeverityLevel::High, "Encrypt personal data at rest and in transit", "gdpr"),
            ("GDPR - Access Controls", "CWE-284", SeverityLevel::High, "Implement role-based access controls", "gdpr"),
            ("GDPR - Audit Logging", "CWE-778", SeverityLevel::Medium, "Enable comprehensive audit logging", "gdpr"),
            ("SOC2 - Change Management", "CWE-439", SeverityLevel::Medium, "Implement change management procedures", "soc2"),
            ("SOC2 - Incident Response", "CWE-778", SeverityLevel::Medium, "Document incident response procedures", "soc2"),
            ("HIPAA - PHI Protection", "CWE-311", SeverityLevel::Critical, "Encrypt all PHI data", "hipaa"),
            ("HIPAA - Access Audit", "CWE-778", SeverityLevel::High, "Log all access to PHI", "hipaa"),
            ("PCI-DSS - Cardholder Data", "CWE-311", SeverityLevel::Critical, "Encrypt cardholder data", "pci-dss"),
            ("PCI-DSS - Network Segmentation", "CWE-284", SeverityLevel::High, "Segment cardholder data environment", "pci-dss"),
            ("ISO27001 - Risk Assessment", "CWE-693", SeverityLevel::Medium, "Conduct regular risk assessments", "iso27001"),
        ];

        for (check_name, cwe, severity, remediation, framework) in compliance_checks {
            vulnerabilities.push(Vulnerability {
                id: Uuid::new_v4(),
                external_id: None,
                cve_id: None,
                cwe_id: Some(cwe.to_string()),
                title: format!("Compliance: {check_name}"),
                description: format!("Compliance requirement check for {framework} framework"),
                severity,
                cvss_score: None,
                cvss_vector: None,
                status: VulnerabilityStatus::Open,
                scan_type: ScanType::ComplianceCheck,
                affected_component: format!("{} Compliance", framework.to_uppercase()),
                affected_version: None,
                fixed_version: None,
                file_path: None,
                line_number: None,
                remediation: Some(remediation.to_string()),
                references: vec![format!("https://cwe.mitre.org/data/definitions/{}.html", cwe.replace("CWE-", ""))],
                tags: vec!["compliance".to_string(), framework.to_string()],
                first_detected: now,
                last_seen: now,
                resolved_at: None,
                resolved_by: None,
                assigned_to: None,
                notes: Vec::new(),
            });
        }

        Ok(vulnerabilities)
    }

    pub async fn get_vulnerability(&self, id: Uuid) -> Option<Vulnerability> {
        let vulns = self.vulnerabilities.read().await;
        vulns.get(&id).cloned()
    }

    pub async fn get_all_vulnerabilities(&self) -> Vec<Vulnerability> {
        let vulns = self.vulnerabilities.read().await;
        vulns.values().cloned().collect()
    }

    pub async fn get_vulnerabilities_by_severity(&self, severity: SeverityLevel) -> Vec<Vulnerability> {
        let vulns = self.vulnerabilities.read().await;
        vulns
            .values()
            .filter(|v| v.severity == severity)
            .cloned()
            .collect()
    }

    pub async fn get_open_vulnerabilities(&self) -> Vec<Vulnerability> {
        let vulns = self.vulnerabilities.read().await;
        vulns
            .values()
            .filter(|v| v.status == VulnerabilityStatus::Open)
            .cloned()
            .collect()
    }

    pub async fn update_vulnerability_status(
        &self,
        id: Uuid,
        status: VulnerabilityStatus,
        user_id: Option<Uuid>,
    ) -> Result<Vulnerability, ScanError> {
        let mut vulns = self.vulnerabilities.write().await;

        let vuln = vulns
            .get_mut(&id)
            .ok_or_else(|| ScanError::NotFound("Vulnerability not found".to_string()))?;

        vuln.status = status.clone();

        if status == VulnerabilityStatus::Resolved {
            vuln.resolved_at = Some(Utc::now());
            vuln.resolved_by = user_id;
        }

        Ok(vuln.clone())
    }

    pub async fn add_vulnerability_note(
        &self,
        vuln_id: Uuid,
        content: String,
        author_id: Uuid,
    ) -> Result<VulnerabilityNote, ScanError> {
        let mut vulns = self.vulnerabilities.write().await;

        let vuln = vulns
            .get_mut(&vuln_id)
            .ok_or_else(|| ScanError::NotFound("Vulnerability not found".to_string()))?;

        let note = VulnerabilityNote {
            id: Uuid::new_v4(),
            content,
            author_id,
            created_at: Utc::now(),
        };

        vuln.notes.push(note.clone());

        Ok(note)
    }

    pub async fn assign_vulnerability(
        &self,
        vuln_id: Uuid,
        assignee_id: Uuid,
    ) -> Result<Vulnerability, ScanError> {
        let mut vulns = self.vulnerabilities.write().await;

        let vuln = vulns
            .get_mut(&vuln_id)
            .ok_or_else(|| ScanError::NotFound("Vulnerability not found".to_string()))?;

        vuln.assigned_to = Some(assignee_id);
        vuln.status = VulnerabilityStatus::InProgress;

        Ok(vuln.clone())
    }

    pub async fn generate_report(
        &self,
        report_type: ReportType,
        period_start: DateTime<Utc>,
        period_end: DateTime<Utc>,
    ) -> Result<VulnerabilityReport, ScanError> {
        let vulns = self.vulnerabilities.read().await;

        let period_vulns: Vec<Vulnerability> = vulns
            .values()
            .filter(|v| v.first_detected >= period_start && v.first_detected <= period_end)
            .cloned()
            .collect();

        let mut by_severity: HashMap<String, u32> = HashMap::new();
        let mut by_status: HashMap<String, u32> = HashMap::new();
        let mut by_type: HashMap<String, u32> = HashMap::new();

        for vuln in &period_vulns {
            *by_severity
                .entry(format!("{:?}", vuln.severity))
                .or_insert(0) += 1;
            *by_status
                .entry(format!("{:?}", vuln.status))
                .or_insert(0) += 1;
            *by_type
                .entry(format!("{:?}", vuln.scan_type))
                .or_insert(0) += 1;
        }

        let open_count = period_vulns
            .iter()
            .filter(|v| v.status == VulnerabilityStatus::Open)
            .count() as u32;

        let resolved_count = period_vulns
            .iter()
            .filter(|v| v.status == VulnerabilityStatus::Resolved)
            .count() as u32;

        let total = period_vulns.len() as u32;
        let compliance_score = if total > 0 {
            ((total - open_count) as f32 / total as f32) * 100.0
        } else {
            100.0
        };

        let summary = ReportSummary {
            total_vulnerabilities: total,
            new_vulnerabilities: total,
            resolved_vulnerabilities: resolved_count,
            open_vulnerabilities: open_count,
            by_severity,
            by_status,
            by_type,
            mean_time_to_remediate_days: None,
            compliance_score,
        };

        let mut recommendations = Vec::new();

        let critical_count = period_vulns
            .iter()
            .filter(|v| v.severity == SeverityLevel::Critical && v.status == VulnerabilityStatus::Open)
            .count();

        if critical_count > 0 {
            recommendations.push(Recommendation {
                priority: 1,
                title: "Address Critical Vulnerabilities".to_string(),
                description: format!("There are {critical_count} critical vulnerabilities that require immediate attention"),
                affected_count: critical_count as u32,
                estimated_effort: "Immediate".to_string(),
                action_items: vec![
                    "Review and prioritize critical findings".to_string(),
                    "Apply available patches".to_string(),
                    "Implement compensating controls if patches unavailable".to_string(),
                ],
            });
        }

        Ok(VulnerabilityReport {
            id: Uuid::new_v4(),
            generated_at: Utc::now(),
            report_type,
            period_start,
            period_end,
            summary,
            vulnerabilities: period_vulns,
            trends: VulnerabilityTrends {
                total_over_time: Vec::new(),
                by_severity_over_time: HashMap::new(),
                mttr_over_time: Vec::new(),
            },
            recommendations,
        })
    }

    pub async fn get_scan_history(&self, limit: usize) -> Vec<ScanResult> {
        let results = self.scan_results.read().await;
        results.iter().rev().take(limit).cloned().collect()
    }

    pub async fn get_latest_scan(&self) -> Option<ScanResult> {
        let results = self.scan_results.read().await;
        results.last().cloned()
    }

    pub async fn create_policy(&self, policy: SecurityPolicy) -> Result<SecurityPolicy, ScanError> {
        let mut policies = self.policies.write().await;
        policies.insert(policy.id, policy.clone());
        Ok(policy)
    }

    pub async fn get_policy(&self, id: Uuid) -> Option<SecurityPolicy> {
        let policies = self.policies.read().await;
        policies.get(&id).cloned()
    }

    pub async fn get_all_policies(&self) -> Vec<SecurityPolicy> {
        let policies = self.policies.read().await;
        policies.values().cloned().collect()
    }

    pub async fn evaluate_policy(
        &self,
        policy_id: Uuid,
        vulnerability: &Vulnerability,
    ) -> Result<PolicyEvaluationResult, ScanError> {
        let policies = self.policies.read().await;

        let policy = policies
            .get(&policy_id)
            .ok_or_else(|| ScanError::NotFound("Policy not found".to_string()))?;

        if !policy.enabled {
            return Ok(PolicyEvaluationResult {
                policy_id,
                policy_name: policy.name.clone(),
                passed: true,
                action: PolicyAction::LogOnly,
                matched_rules: Vec::new(),
                message: "Policy is disabled".to_string(),
            });
        }

        let mut matched_rules = Vec::new();
        let mut action = PolicyAction::LogOnly;
        let mut passed = true;

        for rule in &policy.rules {
            let rule_matches = match rule.rule_type {
                PolicyRuleType::BlockSeverity => {
                    let threshold = match rule.condition.as_str() {
                        "critical" => SeverityLevel::Critical,
                        "high" => SeverityLevel::High,
                        "medium" => SeverityLevel::Medium,
                        "low" => SeverityLevel::Low,
                        _ => SeverityLevel::Info,
                    };
                    self.severity_meets_threshold(&vulnerability.severity, &threshold)
                }
                PolicyRuleType::BlockPackage => {
                    vulnerability.affected_component == rule.condition
                }
                PolicyRuleType::RequireFix => {
                    vulnerability.fixed_version.is_some() && vulnerability.status == VulnerabilityStatus::Open
                }
                _ => false,
            };

            if rule_matches {
                matched_rules.push(rule.clone());
                if rule.action == PolicyAction::Block {
                    action = PolicyAction::Block;
                    passed = false;
                } else if action != PolicyAction::Block && rule.action == PolicyAction::RequireApproval {
                    action = PolicyAction::RequireApproval;
                    passed = false;
                } else if action == PolicyAction::LogOnly && rule.action == PolicyAction::Warn {
                    action = PolicyAction::Warn;
                }
            }
        }

        if policy.enforcement == PolicyEnforcement::Advisory {
            passed = true;
        }

        Ok(PolicyEvaluationResult {
            policy_id,
            policy_name: policy.name.clone(),
            passed,
            action,
            matched_rules,
            message: if passed {
                "Vulnerability passes policy checks".to_string()
            } else {
                "Vulnerability violates policy".to_string()
            },
        })
    }

    fn severity_meets_threshold(&self, severity: &SeverityLevel, threshold: &SeverityLevel) -> bool {
        let severity_rank = match severity {
            SeverityLevel::Critical => 5,
            SeverityLevel::High => 4,
            SeverityLevel::Medium => 3,
            SeverityLevel::Low => 2,
            SeverityLevel::Info => 1,
        };

        let threshold_rank = match threshold {
            SeverityLevel::Critical => 5,
            SeverityLevel::High => 4,
            SeverityLevel::Medium => 3,
            SeverityLevel::Low => 2,
            SeverityLevel::Info => 1,
        };

        severity_rank >= threshold_rank
    }

    pub async fn update_configuration(
        &self,
        config: ScanConfiguration,
    ) -> Result<ScanConfiguration, ScanError> {
        let mut current_config = self.configuration.write().await;
        *current_config = config.clone();
        Ok(config)
    }

    pub async fn get_configuration(&self) -> ScanConfiguration {
        let config = self.configuration.read().await;
        config.clone()
    }

    pub async fn get_dependencies(&self) -> Vec<DependencyInfo> {
        let deps = self.dependencies.read().await;
        deps.clone()
    }

    pub async fn get_security_metrics(&self) -> SecurityMetrics {
        let vulns = self.vulnerabilities.read().await;
        let results = self.scan_results.read().await;

        let total = vulns.len() as u32;
        let open = vulns
            .values()
            .filter(|v| v.status == VulnerabilityStatus::Open)
            .count() as u32;

        let critical_open = vulns
            .values()
            .filter(|v| {
                v.status == VulnerabilityStatus::Open && v.severity == SeverityLevel::Critical
            })
            .count() as u32;

        let high_open = vulns
            .values()
            .filter(|v| {
                v.status == VulnerabilityStatus::Open && v.severity == SeverityLevel::High
            })
            .count() as u32;

        let last_scan = results.last().map(|r| r.completed_at).flatten();

        SecurityMetrics {
            total_vulnerabilities: total,
            open_vulnerabilities: open,
            critical_open,
            high_open,
            resolved_last_30_days: 0,
            new_last_30_days: 0,
            mean_time_to_remediate_hours: None,
            last_scan_time: last_scan,
            scan_coverage_percent: 100.0,
            policy_compliance_percent: if total > 0 {
                ((total - critical_open) as f32 / total as f32) * 100.0
            } else {
                100.0
            },
        }
    }
}

impl Default for VulnerabilityScannerService {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyEvaluationResult {
    pub policy_id: Uuid,
    pub policy_name: String,
    pub passed: bool,
    pub action: PolicyAction,
    pub matched_rules: Vec<PolicyRule>,
    pub message: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityMetrics {
    pub total_vulnerabilities: u32,
    pub open_vulnerabilities: u32,
    pub critical_open: u32,
    pub high_open: u32,
    pub resolved_last_30_days: u32,
    pub new_last_30_days: u32,
    pub mean_time_to_remediate_hours: Option<f32>,
    pub last_scan_time: Option<DateTime<Utc>>,
    pub scan_coverage_percent: f32,
    pub policy_compliance_percent: f32,
}

#[derive(Debug, Clone)]
pub enum ScanError {
    NotFound(String),
    ScanFailed(String),
    ConfigurationError(String),
    NetworkError(String),
    PermissionDenied(String),
    Timeout(String),
    InvalidInput(String),
}

impl std::fmt::Display for ScanError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::NotFound(msg) => write!(f, "Not found: {msg}"),
            Self::ScanFailed(msg) => write!(f, "Scan failed: {msg}"),
            Self::ConfigurationError(msg) => write!(f, "Configuration error: {msg}"),
            Self::NetworkError(msg) => write!(f, "Network error: {msg}"),
            Self::PermissionDenied(msg) => write!(f, "Permission denied: {msg}"),
            Self::Timeout(msg) => write!(f, "Timeout: {msg}"),
            Self::InvalidInput(msg) => write!(f, "Invalid input: {msg}"),
        }
    }
}

impl std::error::Error for ScanError {}
