#[cfg(test)]
mod config_tests {
    use dd0c_route::config::{AppConfig, AuthMode, GovernanceMode};

    #[test]
    fn default_config_from_empty_env() {
        // Clear any existing env vars
        std::env::remove_var("PROXY_PORT");
        std::env::remove_var("API_PORT");
        std::env::remove_var("AUTH_MODE");
        std::env::remove_var("GOVERNANCE_MODE");

        let config = AppConfig::from_env().unwrap();
        assert_eq!(config.proxy_port, 8080);
        assert_eq!(config.api_port, 3000);
        assert_eq!(config.auth_mode, AuthMode::Local);
        assert_eq!(config.governance_mode, GovernanceMode::Audit);
        assert_eq!(config.telemetry_channel_size, 1000);
    }

    #[test]
    fn provider_url_returns_default_for_unknown() {
        let config = AppConfig::from_env().unwrap();
        let url = config.provider_url("unknown-provider");
        assert_eq!(url, "https://api.openai.com");
    }

    #[test]
    fn provider_key_returns_empty_for_unknown() {
        let config = AppConfig::from_env().unwrap();
        let key = config.provider_key("unknown-provider");
        assert_eq!(key, "");
    }
}

#[cfg(test)]
mod anomaly_tests {
    #[test]
    fn anomaly_threshold_3x_triggers() {
        let avg = 10.0_f64;
        let current = 35.0_f64;
        assert!(current > avg * 3.0, "35 should exceed 3x of 10");
    }

    #[test]
    fn anomaly_threshold_2x_does_not_trigger() {
        let avg = 10.0_f64;
        let current = 25.0_f64;
        assert!(current <= avg * 3.0, "25 should not exceed 3x of 10");
    }

    #[test]
    fn anomaly_zero_average_does_not_divide_by_zero() {
        let avg = 0.0_f64;
        let current = 5.0_f64;
        // Should not trigger (guard: avg > 0.0)
        let triggers = avg > 0.0 && current > avg * 3.0;
        assert!(!triggers);
    }
}

#[cfg(test)]
mod digest_tests {
    use chrono::{NaiveDate, NaiveTime, Weekday};

    fn next_monday_9am(from: chrono::DateTime<chrono::Utc>) -> chrono::DateTime<chrono::Utc> {
        // Re-implement here for testing without importing worker internals
        let days_until_monday = (7 - from.weekday().num_days_from_monday()) % 7;
        let days_until_monday = if days_until_monday == 0 && from.time() >= NaiveTime::from_hms_opt(9, 0, 0).unwrap() {
            7
        } else if days_until_monday == 0 {
            0
        } else {
            days_until_monday
        };
        let target_date = from.date_naive() + chrono::Duration::days(days_until_monday as i64);
        target_date.and_hms_opt(9, 0, 0).unwrap().and_utc()
    }

    #[test]
    fn from_wednesday_goes_to_next_monday() {
        let wed = NaiveDate::from_ymd_opt(2026, 3, 4).unwrap()
            .and_hms_opt(14, 0, 0).unwrap().and_utc();
        let next = next_monday_9am(wed);
        assert_eq!(next.weekday(), Weekday::Mon);
        assert_eq!(next.date_naive(), NaiveDate::from_ymd_opt(2026, 3, 9).unwrap());
    }

    #[test]
    fn from_monday_before_9am_stays_same_day() {
        let mon = NaiveDate::from_ymd_opt(2026, 3, 2).unwrap()
            .and_hms_opt(8, 0, 0).unwrap().and_utc();
        let next = next_monday_9am(mon);
        assert_eq!(next.date_naive(), NaiveDate::from_ymd_opt(2026, 3, 2).unwrap());
    }

    #[test]
    fn from_monday_after_9am_goes_to_next_week() {
        let mon = NaiveDate::from_ymd_opt(2026, 3, 2).unwrap()
            .and_hms_opt(10, 0, 0).unwrap().and_utc();
        let next = next_monday_9am(mon);
        assert_eq!(next.date_naive(), NaiveDate::from_ymd_opt(2026, 3, 9).unwrap());
    }

    #[test]
    fn from_sunday_goes_to_next_day() {
        let sun = NaiveDate::from_ymd_opt(2026, 3, 1).unwrap()
            .and_hms_opt(20, 0, 0).unwrap().and_utc();
        let next = next_monday_9am(sun);
        assert_eq!(next.weekday(), Weekday::Mon);
        assert_eq!(next.date_naive(), NaiveDate::from_ymd_opt(2026, 3, 2).unwrap());
    }
}
