use chrono::{NaiveDateTime, Utc};
use std::sync::Arc;
use tokio::sync::RwLock;

#[derive(Clone, Debug, Default)]
pub struct RuntimeHealthSnapshot {
    pub smtp_status: String,
    pub smtp_detail: Option<String>,
    pub cleanup_status: String,
    pub cleanup_detail: Option<String>,
    pub cleanup_last_success: Option<NaiveDateTime>,
    pub cleanup_last_failure: Option<NaiveDateTime>,
    pub outbound_status: String,
}

#[derive(Clone)]
pub struct RuntimeHealth {
    inner: Arc<RwLock<RuntimeHealthSnapshot>>,
}

impl RuntimeHealth {
    pub fn new(smtp_enabled: bool, outbound_enabled: bool) -> Self {
        Self {
            inner: Arc::new(RwLock::new(RuntimeHealthSnapshot {
                smtp_status: if smtp_enabled {
                    "starting".into()
                } else {
                    "disabled".into()
                },
                cleanup_status: "scheduled".into(),
                outbound_status: if outbound_enabled {
                    "starting".into()
                } else {
                    "disabled".into()
                },
                ..Default::default()
            })),
        }
    }

    pub async fn snapshot(&self) -> RuntimeHealthSnapshot {
        self.inner.read().await.clone()
    }

    pub async fn smtp_healthy(&self, detail: String) {
        let mut health = self.inner.write().await;
        health.smtp_status = "healthy".into();
        health.smtp_detail = Some(detail);
    }

    pub async fn smtp_failed(&self, error: String) {
        let mut health = self.inner.write().await;
        health.smtp_status = "fault".into();
        health.smtp_detail = Some(error);
    }

    pub async fn outbound_status(&self, status: &str) {
        self.inner.write().await.outbound_status = status.into();
    }

    pub async fn cleanup_succeeded(&self) {
        let mut health = self.inner.write().await;
        health.cleanup_status = "healthy".into();
        health.cleanup_detail = None;
        health.cleanup_last_success = Some(Utc::now().naive_utc());
    }

    pub async fn cleanup_failed(&self, error: String) {
        let mut health = self.inner.write().await;
        health.cleanup_status = "fault".into();
        health.cleanup_detail = Some(error);
        health.cleanup_last_failure = Some(Utc::now().naive_utc());
    }
}
