use regex::Regex;

use crate::types::{ImpactType, Location, MigrationImpact, VulnerabilityType};

/// Analyzes the context around vulnerabilities to determine migration impacts
pub struct ImpactAnalyzer {
    db_schema_patterns: Vec<Regex>,
    api_patterns: Vec<Regex>,
}

impl ImpactAnalyzer {
    pub fn new() -> Self {
        Self {
            db_schema_patterns: vec![
                Regex::new(r"(?i)VARCHAR\s*\(\s*(\d+)\s*\)").unwrap(),
                Regex::new(r"(?i)VARBINARY\s*\(\s*(\d+)\s*\)").unwrap(),
                Regex::new(r"(?i)CHAR\s*\(\s*(\d+)\s*\)").unwrap(),
                Regex::new(r"(?i)BINARY\s*\(\s*(\d+)\s*\)").unwrap(),
                Regex::new(r"(?i)BLOB").unwrap(),
                Regex::new(r"(?i)TEXT").unwrap(),
                Regex::new(r"(?i)@Column|@Entity|schema|migration").unwrap(),
                Regex::new(r"(?i)CREATE\s+TABLE|ALTER\s+TABLE").unwrap(),
                Regex::new(r"(?i)db\..*\.create|prisma|sequelize|typeorm|mongoose").unwrap(),
            ],
            api_patterns: vec![
                Regex::new(r"(?i)fetch\s*\(|axios\.|http\.|request\(").unwrap(),
                Regex::new(r"(?i)@(Get|Post|Put|Delete|Patch)|router\.(get|post|put|delete)").unwrap(),
                Regex::new(r"(?i)res\.(send|json)|response\.(send|json)").unwrap(),
                Regex::new(r"(?i)Content-Length|payload|body").unwrap(),
                Regex::new(r"(?i)api/|endpoint|REST|GraphQL").unwrap(),
            ],
        }
    }

    /// Analyze context around a vulnerability to determine additional impacts
    pub fn analyze_context(
        &self,
        source: &str,
        location: &Location,
        vuln_type: &VulnerabilityType,
    ) -> Vec<MigrationImpact> {
        let mut impacts = Vec::new();

        // Get surrounding context (50 lines before and after)
        let lines: Vec<&str> = source.lines().collect();
        let start = location.line.saturating_sub(50);
        let end = (location.line + 50).min(lines.len());
        let context: String = lines[start..end].join("\n");

        // Check for database schema impacts
        if self.has_db_context(&context) {
            impacts.push(self.create_db_impact(vuln_type));
        }

        // Check for API payload impacts
        if self.has_api_context(&context) {
            impacts.push(self.create_api_impact(vuln_type));
        }

        // Add architectural impact for asymmetric crypto
        if self.is_asymmetric_crypto(vuln_type) {
            impacts.push(self.create_architectural_impact(vuln_type));
        }

        // Check for certificate/PKI context
        if self.has_certificate_context(&context) {
            impacts.push(self.create_certificate_impact(vuln_type));
        }

        impacts
    }

    fn has_db_context(&self, context: &str) -> bool {
        self.db_schema_patterns.iter().any(|p| p.is_match(context))
    }

    fn has_api_context(&self, context: &str) -> bool {
        self.api_patterns.iter().any(|p| p.is_match(context))
    }

    fn has_certificate_context(&self, context: &str) -> bool {
        let cert_patterns = [
            "certificate",
            "cert",
            ".pem",
            ".crt",
            ".key",
            "x509",
            "X509",
            "PKI",
            "CA",
            "ssl",
            "tls",
        ];
        let lower = context.to_lowercase();
        cert_patterns.iter().any(|p| lower.contains(&p.to_lowercase()))
    }

    fn is_asymmetric_crypto(&self, vuln_type: &VulnerabilityType) -> bool {
        matches!(
            vuln_type,
            VulnerabilityType::Rsa1024
                | VulnerabilityType::Rsa2048
                | VulnerabilityType::Rsa4096
                | VulnerabilityType::RsaOther
                | VulnerabilityType::Ecdsa
                | VulnerabilityType::Ecdh
                | VulnerabilityType::EcdsaP256
                | VulnerabilityType::EcdsaP384
                | VulnerabilityType::EcdsaP521
                | VulnerabilityType::Dsa
                | VulnerabilityType::Dh
                | VulnerabilityType::DhKeyExchange
        )
    }

    fn create_db_impact(&self, vuln_type: &VulnerabilityType) -> MigrationImpact {
        let (key_size, new_size) = match vuln_type {
            VulnerabilityType::Rsa2048 => ("256 bytes", "1184 bytes (Kyber-768)"),
            VulnerabilityType::Rsa4096 => ("512 bytes", "1568 bytes (Kyber-1024)"),
            VulnerabilityType::Ecdsa | VulnerabilityType::EcdsaP256 => ("64 bytes", "2420 bytes (Dilithium2)"),
            VulnerabilityType::EcdsaP384 | VulnerabilityType::EcdsaP521 => ("96-132 bytes", "4000 bytes (Dilithium3)"),
            _ => ("varies", "significantly larger"),
        };

        MigrationImpact {
            impact_type: ImpactType::DatabaseSchema,
            description: format!(
                "Database columns storing cryptographic keys will need expansion. \
                Current key size: {}. PQC key size: {}. \
                Columns like VARCHAR(512) will be insufficient.",
                key_size, new_size
            ),
            affected_components: vec!["Database schema".to_string(), "Key storage tables".to_string()],
            estimated_effort: "Medium".to_string(),
            recommendation: format!(
                "1. Audit all database columns storing keys/signatures\n\
                2. Expand VARCHAR/VARBINARY columns to at least 4096 bytes\n\
                3. Consider using BLOB/BYTEA for maximum flexibility\n\
                4. Plan migration scripts for existing data"
            ),
        }
    }

    fn create_api_impact(&self, vuln_type: &VulnerabilityType) -> MigrationImpact {
        let size_increase = match vuln_type {
            VulnerabilityType::Rsa2048 => "~5x larger keys",
            VulnerabilityType::Ecdsa | VulnerabilityType::EcdsaP256 => "~40x larger signatures",
            _ => "significantly larger payloads",
        };

        MigrationImpact {
            impact_type: ImpactType::ApiPayload,
            description: format!(
                "API payloads containing cryptographic data will increase in size ({}). \
                This may affect request/response size limits, network latency, and bandwidth costs.",
                size_increase
            ),
            affected_components: vec![
                "API endpoints".to_string(),
                "Network layer".to_string(),
                "Client applications".to_string(),
            ],
            estimated_effort: "Low to Medium".to_string(),
            recommendation: format!(
                "1. Review API payload size limits\n\
                2. Consider compression for cryptographic payloads\n\
                3. Evaluate impact on mobile/low-bandwidth clients\n\
                4. Monitor API latency after migration"
            ),
        }
    }

    fn create_architectural_impact(&self, vuln_type: &VulnerabilityType) -> MigrationImpact {
        let change_type = match vuln_type {
            VulnerabilityType::Rsa1024
            | VulnerabilityType::Rsa2048
            | VulnerabilityType::Rsa4096
            | VulnerabilityType::RsaOther => {
                "RSA direct encryption must be replaced with Key Encapsulation Mechanism (KEM) pattern"
            }
            VulnerabilityType::Ecdh | VulnerabilityType::Dh | VulnerabilityType::DhKeyExchange => {
                "Key exchange protocol must migrate from DH/ECDH to Kyber KEM"
            }
            VulnerabilityType::Ecdsa | VulnerabilityType::Dsa => {
                "Digital signature scheme must migrate to Dilithium or SPHINCS+"
            }
            _ => "Cryptographic operations require architectural changes",
        };

        MigrationImpact {
            impact_type: ImpactType::ArchitecturalRefactor,
            description: format!(
                "{}. This is not a drop-in replacement and requires changes to the encryption/signing logic.",
                change_type
            ),
            affected_components: vec![
                "Encryption modules".to_string(),
                "Key management".to_string(),
                "Protocol handlers".to_string(),
            ],
            estimated_effort: "High".to_string(),
            recommendation: format!(
                "1. Understand the KEM paradigm (encapsulate/decapsulate vs encrypt/decrypt)\n\
                2. Design hybrid approach for transition period\n\
                3. Update key generation, storage, and usage code\n\
                4. Implement proper error handling for new algorithm types\n\
                5. Consider using abstraction layer for algorithm agility"
            ),
        }
    }

    fn create_certificate_impact(&self, _vuln_type: &VulnerabilityType) -> MigrationImpact {
        MigrationImpact {
            impact_type: ImpactType::CertificateInfrastructure,
            description: "TLS certificates and PKI infrastructure will need migration to PQC algorithms. \
                This affects certificate chains, CAs, and all TLS endpoints.".to_string(),
            affected_components: vec![
                "TLS certificates".to_string(),
                "Certificate Authority".to_string(),
                "PKI infrastructure".to_string(),
                "Trust stores".to_string(),
            ],
            estimated_effort: "High".to_string(),
            recommendation: format!(
                "1. Inventory all certificates and their expiration dates\n\
                2. Plan migration timeline aligned with certificate renewals\n\
                3. Prepare for hybrid certificates during transition\n\
                4. Update certificate validation logic\n\
                5. Coordinate with CA for PQC certificate issuance"
            ),
        }
    }
}
