//! Autonomous promotion configuration.
//!
//! Controls when learned patterns can skip human review and be
//! automatically promoted to declarative extractors.

use std::path::PathBuf;

use serde::Deserialize;

/// Autonomous promotion configuration.
///
/// Controls when patterns can skip human review.
/// Thresholds are STRICTER than `[learning.promotion]` by default.
///
/// # Safety Design
///
/// - **Kill switch**: `enabled` defaults to `false` (opt-in only)
/// - **Auditability**: All decisions logged to JSONL
/// - **Reversibility**: Can delete YAML + reset pattern.promoted
/// - **Blast radius**: One pattern = one YAML file
/// - **Traceability**: YAML header shows "AUTO-PROMOTED" + "Approved by: autonomous"
///
/// # Configuration
///
/// ```toml
/// [autonomous]
/// enabled = true            # Master switch (default: false)
/// min_confidence = 0.95     # Stricter than promotion threshold
/// min_projects = 10         # Stricter than promotion threshold
/// require_zero_failures = true
/// require_zero_warnings = true
/// audit_log = true
/// audit_dir = "~/.aphoria/audit/"
/// ```
#[derive(Debug, Clone, Deserialize)]
#[serde(default)]
pub struct AutonomousConfig {
    /// Master kill switch (default: false - opt-in only).
    ///
    /// When false, no patterns will be auto-promoted regardless
    /// of other settings. This is the primary safety mechanism.
    pub enabled: bool,

    /// Minimum average confidence across all observations.
    ///
    /// Default: 0.95 (stricter than standard promotion threshold of 0.8).
    /// Only patterns with very high LLM confidence are eligible.
    pub min_confidence: f32,

    /// Minimum number of unique projects where pattern was observed.
    ///
    /// Default: 10 (stricter than standard promotion threshold of 5).
    /// Ensures pattern has been validated across many codebases.
    pub min_projects: usize,

    /// Require zero positive test failures.
    ///
    /// When true, any pattern whose generated regex fails to match
    /// the original example code will be excluded from auto-promotion.
    pub require_zero_failures: bool,

    /// Require zero validation warnings.
    ///
    /// When true, patterns with any warnings (false positive risk,
    /// performance concerns, etc.) will be excluded from auto-promotion.
    pub require_zero_warnings: bool,

    /// Enable audit logging.
    ///
    /// When true, all autonomous decisions (promoted or not) are
    /// written to a JSONL file for review and compliance.
    pub audit_log: bool,

    /// Directory for audit logs.
    ///
    /// Default: `~/.aphoria/audit/`
    /// Logs are written to `autonomous-decisions.jsonl` in this directory.
    pub audit_dir: Option<PathBuf>,
}

impl AutonomousConfig {
    /// Check if autonomous promotion is enabled.
    pub fn is_enabled(&self) -> bool {
        self.enabled
    }

    /// Get the audit directory, using defaults if not specified.
    pub fn get_audit_dir(&self) -> PathBuf {
        if let Some(ref dir) = self.audit_dir {
            dir.clone()
        } else if let Some(home) = dirs::home_dir() {
            home.join(".aphoria").join("audit")
        } else {
            PathBuf::from(".aphoria/audit")
        }
    }
}

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

    #[test]
    fn test_default_is_disabled() {
        let config = AutonomousConfig::default();
        assert!(!config.enabled, "Kill switch must default to off");
    }

    #[test]
    fn test_default_thresholds_are_strict() {
        let config = AutonomousConfig::default();
        assert!(config.min_confidence >= 0.95, "Default confidence threshold must be high");
        assert!(config.min_projects >= 10, "Default project threshold must be high");
    }

    #[test]
    fn test_deserialize_with_defaults() {
        let toml = r#"
            enabled = true
            min_confidence = 0.97
        "#;

        let config: AutonomousConfig = toml::from_str(toml).expect("parse");
        assert!(config.enabled);
        assert!((config.min_confidence - 0.97).abs() < 0.001);
        // Other fields should use defaults
        assert_eq!(config.min_projects, 10);
        assert!(config.require_zero_failures);
    }

    #[test]
    fn test_get_audit_dir_with_explicit() {
        let config = AutonomousConfig {
            audit_dir: Some(PathBuf::from("/custom/audit")),
            ..Default::default()
        };
        assert_eq!(config.get_audit_dir(), PathBuf::from("/custom/audit"));
    }

    #[test]
    fn test_get_audit_dir_uses_home() {
        let config = AutonomousConfig::default();
        let dir = config.get_audit_dir();
        // Should end with .aphoria/audit
        assert!(dir.ends_with("audit"));
    }
}
