//! Default implementations for configuration types.

use std::path::PathBuf;

use super::types::{
    AliasConfig, AutonomousConfig, CommunityConfig, CorpusConfig, DepVersionConfig, EntropyConfig,
    EpistemeConfig, ExtractorConfig, HostedConfig, LearningConfig, LlmConfig, OfflineFallback,
    PromotionConfig, ScanConfig, SyncMode, ThresholdConfig, TimeoutExtractorConfig,
    DEFAULT_LLM_MODEL,
};

impl Default for EpistemeConfig {
    fn default() -> Self {
        Self { data_dir: dirs_default_data_dir(), url: None }
    }
}

impl Default for ThresholdConfig {
    fn default() -> Self {
        Self { block: 0.7, flag: 0.4 }
    }
}

impl Default for ExtractorConfig {
    fn default() -> Self {
        Self {
            enabled: vec![
                "tls_verify".to_string(),
                "tls_version".to_string(),
                "jwt_config".to_string(),
                "hardcoded_secrets".to_string(),
                "timeout_config".to_string(),
                "dep_versions".to_string(),
                "cors_config".to_string(),
                "durability_config".to_string(),
                "rate_limit".to_string(),
                // Phase 2 extractors
                "weak_crypto".to_string(),
                "sql_injection".to_string(),
                "command_injection".to_string(),
                // Unreal Engine extractors
                "unreal_cpp".to_string(),
                "unreal_config".to_string(),
                "unreal_performance".to_string(),
                // Phase 8: Enterprise extractors (first batch)
                "high_entropy_secrets".to_string(),
                "auth_bypass".to_string(),
                "api_key_security".to_string(),
                "import_graph".to_string(),
                "derive_pattern".to_string(),
                "const_declarations".to_string(),
                "unsafe_atomic".to_string(),
                "circuit_breaker_config".to_string(),
                "insecure_cookies".to_string(),
                // Phase 8: Enterprise extractors (second batch)
                "path_traversal".to_string(),
                "unvalidated_redirects".to_string(),
                "weak_password".to_string(),
                "security_headers".to_string(),
                "insecure_deserialization".to_string(),
                "ssrf".to_string(),
                "orm_injection".to_string(),
                "xxe".to_string(),
                // Phase 8.3: Config deep parsing
                "config_security".to_string(),
                // Phase 8.2: Framework-specific security extractors
                "django_security".to_string(),
                "express_security".to_string(),
                "flask_security".to_string(),
                "fastapi_security".to_string(),
                "nestjs_security".to_string(),
                "nextjs_security".to_string(),
                "spring_security".to_string(),
                "laravel_security".to_string(),
                "rails_security".to_string(),
                "aspnet_security".to_string(),
            ],
            disabled: vec![],
            timeout_config: TimeoutExtractorConfig::default(),
            dep_versions: DepVersionConfig::default(),
            entropy: EntropyConfig::default(),
            declarative: vec![],
        }
    }
}

impl Default for TimeoutExtractorConfig {
    fn default() -> Self {
        Self { min_reasonable_ms: 1000, max_reasonable_ms: 300_000 }
    }
}

impl Default for DepVersionConfig {
    fn default() -> Self {
        Self {
            enabled: false, // OPT-IN: Disabled by default to reduce noise
            advisory_db: dirs_default_advisory_db(),
        }
    }
}

impl Default for EntropyConfig {
    fn default() -> Self {
        Self { min_entropy: 4.5, min_charset_variety: 0.4, min_length: 20, max_length: 200 }
    }
}

impl Default for ScanConfig {
    fn default() -> Self {
        Self {
            exclude: vec![
                "target/".to_string(),
                "node_modules/".to_string(),
                ".git/".to_string(),
                "vendor/".to_string(),
            ],
            max_file_size: 1_048_576, // 1MB
            include_tests: false,
        }
    }
}

impl Default for AliasConfig {
    fn default() -> Self {
        Self { auto_suggest: true, auto_accept_tier0: true, auto_create_aliases: true }
    }
}

impl Default for CorpusConfig {
    fn default() -> Self {
        Self {
            cache_dir: dirs_default_cache_dir(),
            include_hardcoded: true,
            include_rfc: true,
            include_owasp: true,
            include_vendor: true,
            rfc_list: None,
        }
    }
}

impl Default for HostedConfig {
    fn default() -> Self {
        Self {
            url: None,
            project_id: None,
            team_id: None,
            sync_mode: SyncMode::default(),
            offline_fallback: OfflineFallback::default(),
            max_retries: 3,
            retry_delay_ms: 1000,
            api_key_env: "APHORIA_API_KEY".to_string(),
        }
    }
}

impl Default for CommunityConfig {
    fn default() -> Self {
        Self {
            enabled: false,  // CRITICAL: Opt-in only
            anonymize: true, // CRITICAL: Privacy by default
            exclude: vec![],
            include: vec![],
            min_confidence: 0.8,
        }
    }
}

impl Default for LlmConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            provider: "gemini".to_string(),
            model: DEFAULT_LLM_MODEL.to_string(),
            api_key_env: "GEMINI_API_KEY".to_string(),
            max_tokens_per_scan: 50000,
            max_tokens_per_file: 4000,
            cache_responses: true,
            timeout_secs: 60,
            high_value_only: true,
            min_confidence: 0.7,
        }
    }
}

impl Default for LearningConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            store: "local".to_string(),
            min_confidence: 0.7,
            prune_after_days: 90,
            max_patterns: 10_000,
            promotion: PromotionConfig::default(),
        }
    }
}

impl Default for PromotionConfig {
    fn default() -> Self {
        Self {
            min_projects: 5,
            min_confidence: 0.8,
            auto_promote: false,
            output_dir: PathBuf::from(".aphoria/extractors/learned"),
            require_review: true,
        }
    }
}

impl Default for AutonomousConfig {
    fn default() -> Self {
        Self {
            // CRITICAL: Opt-in only - kill switch defaults to off
            enabled: false,
            // Stricter than standard promotion thresholds
            min_confidence: 0.95,
            min_projects: 10,
            // Require perfect validation by default
            require_zero_failures: true,
            require_zero_warnings: true,
            // Audit logging on by default for compliance
            audit_log: true,
            audit_dir: None, // Uses ~/.aphoria/audit/ via get_audit_dir()
        }
    }
}

/// Get the default Aphoria data directory.
fn dirs_default_data_dir() -> PathBuf {
    if let Some(home) = dirs::home_dir() {
        home.join(".aphoria").join("db")
    } else {
        PathBuf::from(".aphoria/db")
    }
}

/// Get the default advisory database directory.
fn dirs_default_advisory_db() -> PathBuf {
    if let Some(home) = dirs::home_dir() {
        home.join(".aphoria").join("advisory-db")
    } else {
        PathBuf::from(".aphoria/advisory-db")
    }
}

/// Get the default cache directory for corpus downloads.
fn dirs_default_cache_dir() -> PathBuf {
    if let Some(cache) = dirs::cache_dir() {
        cache.join("aphoria")
    } else if let Some(home) = dirs::home_dir() {
        home.join(".cache").join("aphoria")
    } else {
        PathBuf::from(".aphoria/cache")
    }
}

/// Get the LLM response cache directory.
///
/// Used to cache Claude API responses keyed by content hash + model.
/// This avoids redundant API calls for the same file content.
pub fn llm_cache_dir() -> PathBuf {
    if let Some(cache) = dirs::cache_dir() {
        cache.join("aphoria").join("llm-cache")
    } else if let Some(home) = dirs::home_dir() {
        home.join(".cache").join("aphoria").join("llm-cache")
    } else {
        PathBuf::from(".aphoria/llm-cache")
    }
}
