//! Kotlin-specific quantum vulnerability detection
//! 
//! Detects quantum-vulnerable cryptographic patterns in Kotlin code including:
//! - RSA key generation and encryption (KeyPairGenerator, Cipher)
//! - ECDSA/ECDH operations (EC, Signature)
//! - DSA signatures
//! - Weak hash functions (MD5, SHA-1)
//! - Weak ciphers (DES, 3DES, RC4)
//! - Weak random (Random vs SecureRandom)
//! - BouncyCastle patterns

use std::path::Path;
use regex::Regex;
use uuid::Uuid;

use crate::types::{Language, Location, Severity, Vulnerability, VulnerabilityType};

/// Kotlin-specific vulnerability analyzer using regex patterns
pub struct KotlinAnalyzer {
    patterns: Vec<KotlinPattern>,
}

struct KotlinPattern {
    regex: Regex,
    vuln_type: VulnerabilityType,
    severity: Severity,
    description: &'static str,
    recommendation: &'static str,
    cwe_id: Option<&'static str>,
}

impl KotlinAnalyzer {
    pub fn new() -> Self {
        Self {
            patterns: Self::compile_patterns(),
        }
    }

    fn compile_patterns() -> Vec<KotlinPattern> {
        let pattern_defs: Vec<(&str, VulnerabilityType, Severity, &'static str, &'static str, Option<&'static str>)> = vec![
            // =============================================
            // RSA VULNERABILITIES
            // =============================================
            (
                r#"(?i)KeyPairGenerator\s*\.\s*getInstance\s*\(\s*["']RSA["']"#,
                VulnerabilityType::Rsa2048,
                Severity::Critical,
                "Kotlin RSA KeyPairGenerator detected",
                "Migrate to post-quantum cryptography using BouncyCastle PQC provider",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Cipher\s*\.\s*getInstance\s*\([^)]*RSA[^)]*\)"#,
                VulnerabilityType::Rsa2048,
                Severity::Critical,
                "Kotlin RSA Cipher instance detected",
                "Replace RSA encryption with hybrid PQC scheme",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Signature\s*\.\s*getInstance\s*\([^)]*RSA[^)]*\)"#,
                VulnerabilityType::Rsa2048,
                Severity::Critical,
                "Kotlin RSA Signature instance detected",
                "Migrate to CRYSTALS-Dilithium for digital signatures",
                Some("CWE-327"),
            ),
            (
                r"(?i)RSAKeyGenParameterSpec|RSAPublicKeySpec|RSAPrivateKeySpec",
                VulnerabilityType::Rsa2048,
                Severity::Critical,
                "Kotlin RSA key specification detected",
                "Use post-quantum key exchange mechanisms",
                Some("CWE-327"),
            ),
            (
                r"(?i)\.generateKeyPair\s*\(\s*\).*RSA|RSA.*\.generateKeyPair\s*\(\s*\)",
                VulnerabilityType::Rsa2048,
                Severity::Critical,
                "Kotlin RSA key pair generation",
                "Migrate to CRYSTALS-Kyber for key encapsulation",
                Some("CWE-327"),
            ),

            // =============================================
            // ECDSA/ECDH VULNERABILITIES
            // =============================================
            (
                r#"(?i)KeyPairGenerator\s*\.\s*getInstance\s*\(\s*["']EC["']"#,
                VulnerabilityType::Ecdsa,
                Severity::Critical,
                "Kotlin EC KeyPairGenerator detected",
                "Migrate to post-quantum cryptography",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Signature\s*\.\s*getInstance\s*\([^)]*ECDSA[^)]*\)"#,
                VulnerabilityType::Ecdsa,
                Severity::Critical,
                "Kotlin ECDSA Signature instance detected",
                "Migrate to CRYSTALS-Dilithium for digital signatures",
                Some("CWE-327"),
            ),
            (
                r#"(?i)KeyAgreement\s*\.\s*getInstance\s*\(\s*["']ECDH["']"#,
                VulnerabilityType::Ecdh,
                Severity::Critical,
                "Kotlin ECDH KeyAgreement detected",
                "Replace with CRYSTALS-Kyber KEM",
                Some("CWE-327"),
            ),
            (
                r"(?i)ECGenParameterSpec|ECParameterSpec|ECPublicKeySpec|ECPrivateKeySpec",
                VulnerabilityType::Ecdsa,
                Severity::Critical,
                "Kotlin EC key specification detected",
                "Migrate to post-quantum alternatives",
                Some("CWE-327"),
            ),
            (
                r#"(?i)["'](secp256k1|secp384r1|secp521r1|P-256|P-384|P-521|prime256v1)["']"#,
                VulnerabilityType::Ecdsa,
                Severity::Critical,
                "Kotlin elliptic curve parameter detected",
                "All classical EC curves are quantum-vulnerable",
                Some("CWE-327"),
            ),

            // =============================================
            // DSA VULNERABILITIES
            // =============================================
            (
                r#"(?i)KeyPairGenerator\s*\.\s*getInstance\s*\(\s*["']DSA["']"#,
                VulnerabilityType::Dsa,
                Severity::Critical,
                "Kotlin DSA KeyPairGenerator detected",
                "Migrate to CRYSTALS-Dilithium or SPHINCS+",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Signature\s*\.\s*getInstance\s*\([^)]*DSA[^)]*\)"#,
                VulnerabilityType::Dsa,
                Severity::Critical,
                "Kotlin DSA Signature instance detected",
                "Replace DSA with post-quantum signatures",
                Some("CWE-327"),
            ),

            // =============================================
            // DIFFIE-HELLMAN VULNERABILITIES
            // =============================================
            (
                r#"(?i)KeyPairGenerator\s*\.\s*getInstance\s*\(\s*["']DH["']|["']DiffieHellman["']"#,
                VulnerabilityType::DhKeyExchange,
                Severity::Critical,
                "Kotlin Diffie-Hellman KeyPairGenerator detected",
                "Replace with CRYSTALS-Kyber KEM",
                Some("CWE-327"),
            ),
            (
                r#"(?i)KeyAgreement\s*\.\s*getInstance\s*\(\s*["']DH["']|["']DiffieHellman["']"#,
                VulnerabilityType::DhKeyExchange,
                Severity::Critical,
                "Kotlin Diffie-Hellman KeyAgreement detected",
                "Replace with CRYSTALS-Kyber KEM",
                Some("CWE-327"),
            ),
            (
                r"(?i)DHParameterSpec|DHGenParameterSpec|DHPublicKeySpec|DHPrivateKeySpec",
                VulnerabilityType::DhKeyExchange,
                Severity::Critical,
                "Kotlin DH parameter specification detected",
                "Migrate to post-quantum key exchange",
                Some("CWE-327"),
            ),

            // =============================================
            // WEAK HASH FUNCTIONS
            // =============================================
            (
                r#"(?i)MessageDigest\s*\.\s*getInstance\s*\(\s*["']MD5["']"#,
                VulnerabilityType::Md5,
                Severity::High,
                "Kotlin MD5 MessageDigest detected",
                "Replace with SHA-256 or SHA-3",
                Some("CWE-328"),
            ),
            (
                r#"(?i)MessageDigest\s*\.\s*getInstance\s*\(\s*["']SHA-?1["']"#,
                VulnerabilityType::Sha1,
                Severity::High,
                "Kotlin SHA-1 MessageDigest detected",
                "Replace with SHA-256 or SHA-3",
                Some("CWE-328"),
            ),
            (
                r#"(?i)Mac\s*\.\s*getInstance\s*\(\s*["']HmacMD5["']"#,
                VulnerabilityType::Md5,
                Severity::High,
                "Kotlin HMAC-MD5 detected",
                "Replace with HMAC-SHA256",
                Some("CWE-328"),
            ),
            (
                r#"(?i)Mac\s*\.\s*getInstance\s*\(\s*["']HmacSHA1["']"#,
                VulnerabilityType::Sha1,
                Severity::High,
                "Kotlin HMAC-SHA1 detected",
                "Replace with HMAC-SHA256",
                Some("CWE-328"),
            ),

            // =============================================
            // WEAK CIPHERS
            // =============================================
            (
                r#"(?i)Cipher\s*\.\s*getInstance\s*\(\s*["']DES[/"']"#,
                VulnerabilityType::Des,
                Severity::Critical,
                "Kotlin DES Cipher detected",
                "Replace with AES-256-GCM",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Cipher\s*\.\s*getInstance\s*\(\s*["']DESede[/"']|["']3DES[/"']"#,
                VulnerabilityType::TripleDes,
                Severity::High,
                "Kotlin 3DES/DESede Cipher detected",
                "Replace with AES-256-GCM",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Cipher\s*\.\s*getInstance\s*\(\s*["']RC4["']|["']ARCFOUR["']"#,
                VulnerabilityType::Rc4,
                Severity::Critical,
                "Kotlin RC4/ARCFOUR Cipher detected",
                "Replace with AES-256-GCM or ChaCha20-Poly1305",
                Some("CWE-327"),
            ),
            (
                r#"(?i)Cipher\s*\.\s*getInstance\s*\(\s*["']Blowfish["']"#,
                VulnerabilityType::Blowfish,
                Severity::Medium,
                "Kotlin Blowfish Cipher detected",
                "Replace with AES-256-GCM",
                Some("CWE-327"),
            ),

            // =============================================
            // WEAK RANDOM
            // =============================================
            (
                r"(?i)\bRandom\s*\(\s*\)|java\.util\.Random\s*\(\s*\)|kotlin\.random\.Random(?!\.Secure)",
                VulnerabilityType::WeakRandom,
                Severity::High,
                "Kotlin weak Random detected",
                "Use SecureRandom for cryptographic purposes",
                Some("CWE-338"),
            ),
            (
                r"(?i)\.nextInt\s*\(|\.nextLong\s*\(|\.nextDouble\s*\(|\.nextBytes\s*\(",
                VulnerabilityType::WeakRandom,
                Severity::Medium,
                "Potential weak random usage in Kotlin",
                "Ensure SecureRandom is used for cryptographic operations",
                Some("CWE-338"),
            ),

            // =============================================
            // INSECURE TLS
            // =============================================
            (
                r#"(?i)SSLContext\s*\.\s*getInstance\s*\(\s*["'](SSLv2|SSLv3|TLSv1|TLSv1\.0|TLSv1\.1)["']"#,
                VulnerabilityType::InsecureTls,
                Severity::High,
                "Kotlin insecure TLS/SSL version detected",
                "Use TLS 1.2 or TLS 1.3",
                Some("CWE-326"),
            ),
            (
                r"(?i)setEnabledProtocols.*SSLv|setEnabledProtocols.*TLSv1[^.]",
                VulnerabilityType::InsecureTls,
                Severity::High,
                "Kotlin legacy TLS protocol enabled",
                "Only enable TLS 1.2 and TLS 1.3",
                Some("CWE-326"),
            ),

            // =============================================
            // BOUNCYCASTLE PATTERNS
            // =============================================
            (
                r"(?i)RSAEngine|RSAKeyPairGenerator|RSABlindedEngine",
                VulnerabilityType::Rsa2048,
                Severity::Critical,
                "Kotlin BouncyCastle RSA engine detected",
                "Use BouncyCastle PQC provider for post-quantum algorithms",
                Some("CWE-327"),
            ),
            (
                r"(?i)ECKeyPairGenerator|ECDSA|ECDHBasic|ECDHKEKGenerator",
                VulnerabilityType::Ecdsa,
                Severity::Critical,
                "Kotlin BouncyCastle EC operations detected",
                "Migrate to BouncyCastle Dilithium or Kyber",
                Some("CWE-327"),
            ),
            (
                r"(?i)DSAKeyPairGenerator|DSASigner",
                VulnerabilityType::Dsa,
                Severity::Critical,
                "Kotlin BouncyCastle DSA detected",
                "Migrate to Dilithium or SPHINCS+",
                Some("CWE-327"),
            ),
            (
                r"(?i)DHKeyPairGenerator|DHBasicAgreement|DHParameters",
                VulnerabilityType::DhKeyExchange,
                Severity::Critical,
                "Kotlin BouncyCastle DH detected",
                "Use Kyber KEM for key exchange",
                Some("CWE-327"),
            ),

            // =============================================
            // EDWARDS CURVES (Quantum-vulnerable)
            // =============================================
            (
                r"(?i)\b(Ed25519|Ed448|X25519|X448|Curve25519)\b",
                VulnerabilityType::Ecdsa,
                Severity::Critical,
                "Kotlin Edwards curve cryptography detected",
                "Edwards curves are quantum-vulnerable, migrate to Dilithium",
                Some("CWE-327"),
            ),
        ];

        pattern_defs
            .into_iter()
            .filter_map(|(pattern, vuln_type, severity, desc, rec, cwe)| {
                Regex::new(pattern).ok().map(|regex| KotlinPattern {
                    regex,
                    vuln_type,
                    severity,
                    description: desc,
                    recommendation: rec,
                    cwe_id: cwe,
                })
            })
            .collect()
    }

    /// Analyze Kotlin source code for quantum vulnerabilities
    pub fn analyze(&self, source: &str, file_path: &Path) -> Vec<Vulnerability> {
        let mut vulnerabilities = Vec::new();

        for pattern in &self.patterns {
            for mat in pattern.regex.find_iter(source) {
                // Skip if in comment or documentation
                if self.is_in_comment(source, mat.start()) {
                    continue;
                }

                // Skip if in informational string
                if self.is_informational_string(source, mat.start(), mat.end()) {
                    continue;
                }

                let (line, column) = self.offset_to_position(source, mat.start());

                vulnerabilities.push(Vulnerability {
                    id: Uuid::new_v4(),
                    vuln_type: pattern.vuln_type.clone(),
                    severity: pattern.severity,
                    location: Location {
                        file: file_path.to_path_buf(),
                        line,
                        column,
                        end_line: None,
                        end_column: None,
                    },
                    description: pattern.description.to_string(),
                    code_snippet: self.extract_snippet(source, line),
                    recommendation: pattern.recommendation.to_string(),
                    migration_impacts: vec![],
                    cwe_id: pattern.cwe_id.map(|s| s.to_string()),
                    is_dependency: false,
                    dependency_chain: None,
                    finding_type: crate::types::FindingType::DirectUsage,
                    library_name: None,
                });
            }
        }

        vulnerabilities
    }

    fn is_in_comment(&self, source: &str, offset: usize) -> bool {
        let before = &source[..offset];
        
        // Check for single-line comment
        if let Some(line_start) = before.rfind('\n') {
            let line = &before[line_start..];
            if line.contains("//") {
                return true;
            }
        } else if before.contains("//") {
            let comment_pos = before.rfind("//").unwrap();
            if !before[comment_pos..].contains('\n') {
                return true;
            }
        }

        // Check for block comment
        let last_open = before.rfind("/*");
        let last_close = before.rfind("*/");
        
        match (last_open, last_close) {
            (Some(open), Some(close)) => open > close,
            (Some(_), None) => true,
            _ => false,
        }
    }

    fn is_informational_string(&self, source: &str, start: usize, end: usize) -> bool {
        let line_start = source[..start].rfind('\n').map(|p| p + 1).unwrap_or(0);
        let line_end = source[end..].find('\n').map(|p| end + p).unwrap_or(source.len());
        let line = &source[line_start..line_end].to_lowercase();

        let doc_indicators = [
            " is a ", " is an ", " is the ", " provides ", " enables ",
            " named after ", " stands for ", " deprecated ", " vulnerable ",
            " algorithm ", "documentation", "example", "// ", "/* ", "/** ",
        ];

        doc_indicators.iter().any(|ind| line.contains(ind))
    }

    fn offset_to_position(&self, source: &str, offset: usize) -> (usize, usize) {
        let mut line = 1;
        let mut col = 1;

        for (i, c) in source.char_indices() {
            if i >= offset {
                break;
            }
            if c == '\n' {
                line += 1;
                col = 1;
            } else {
                col += 1;
            }
        }

        (line, col)
    }

    fn extract_snippet(&self, source: &str, line: usize) -> Option<String> {
        let lines: Vec<&str> = source.lines().collect();
        if line == 0 || line > lines.len() {
            return None;
        }

        let start = line.saturating_sub(2);
        let end = (line + 1).min(lines.len());

        let snippet: Vec<String> = lines[start..end]
            .iter()
            .enumerate()
            .map(|(i, l)| format!("{:4} | {}", start + i + 1, l))
            .collect();

        Some(snippet.join("\n"))
    }
}

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

    #[test]
    fn test_rsa_detection() {
        let analyzer = KotlinAnalyzer::new();
        let source = r#"
            val keyGen = KeyPairGenerator.getInstance("RSA")
            keyGen.initialize(2048)
        "#;
        let vulns = analyzer.analyze(source, Path::new("test.kt"));
        assert!(!vulns.is_empty());
        assert!(matches!(vulns[0].vuln_type, VulnerabilityType::Rsa2048));
    }

    #[test]
    fn test_md5_detection() {
        let analyzer = KotlinAnalyzer::new();
        let source = r#"
            val md = MessageDigest.getInstance("MD5")
        "#;
        let vulns = analyzer.analyze(source, Path::new("test.kt"));
        assert!(!vulns.is_empty());
        assert!(matches!(vulns[0].vuln_type, VulnerabilityType::Md5));
    }

    #[test]
    fn test_false_positive_comment() {
        let analyzer = KotlinAnalyzer::new();
        let source = r#"
            // RSA is named after Rivest, Shamir, and Adleman
            val x = 42
        "#;
        let vulns = analyzer.analyze(source, Path::new("test.kt"));
        assert!(vulns.is_empty());
    }
}
