#![allow(dead_code)]

//! Stats screen state — database and index statistics.
//!
//! Shows entity counts, FTS coverage, embedding coverage, and queue
//! health. Data is produced by synchronous DB queries.

// ---------------------------------------------------------------------------
// StatsData
// ---------------------------------------------------------------------------

/// Database statistics for TUI display.
#[derive(Debug, Clone, Default)]
pub struct StatsData {
    /// Total documents in the database.
    pub total_documents: i64,
    /// Issues stored.
    pub issues: i64,
    /// Merge requests stored.
    pub merge_requests: i64,
    /// Discussions stored.
    pub discussions: i64,
    /// Notes stored.
    pub notes: i64,
    /// Documents indexed in FTS.
    pub fts_indexed: i64,
    /// Documents with embeddings.
    pub embedded_documents: i64,
    /// Total embedding chunks.
    pub total_chunks: i64,
    /// Embedding coverage percentage (0.0–100.0).
    pub coverage_pct: f64,
    /// Pending queue items (dirty sources).
    pub queue_pending: i64,
    /// Failed queue items.
    pub queue_failed: i64,
}

impl StatsData {
    /// FTS coverage percentage relative to total documents.
    #[must_use]
    pub fn fts_coverage_pct(&self) -> f64 {
        if self.total_documents == 0 {
            0.0
        } else {
            (self.fts_indexed as f64 / self.total_documents as f64) * 100.0
        }
    }

    /// Whether there are pending queue items that need processing.
    #[must_use]
    pub fn has_queue_work(&self) -> bool {
        self.queue_pending > 0 || self.queue_failed > 0
    }
}

// ---------------------------------------------------------------------------
// StatsState
// ---------------------------------------------------------------------------

/// State for the Stats screen.
#[derive(Debug, Default)]
pub struct StatsState {
    /// Statistics data (None until loaded).
    pub data: Option<StatsData>,
    /// Whether data has been loaded at least once.
    pub loaded: bool,
}

impl StatsState {
    /// Apply loaded stats data.
    pub fn apply_data(&mut self, data: StatsData) {
        self.data = Some(data);
        self.loaded = true;
    }
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

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

    fn sample_stats() -> StatsData {
        StatsData {
            total_documents: 500,
            issues: 200,
            merge_requests: 150,
            discussions: 100,
            notes: 50,
            fts_indexed: 450,
            embedded_documents: 300,
            total_chunks: 1200,
            coverage_pct: 60.0,
            queue_pending: 5,
            queue_failed: 1,
        }
    }

    #[test]
    fn test_default_state() {
        let state = StatsState::default();
        assert!(state.data.is_none());
        assert!(!state.loaded);
    }

    #[test]
    fn test_apply_data() {
        let mut state = StatsState::default();
        state.apply_data(sample_stats());
        assert!(state.loaded);
        assert!(state.data.is_some());
    }

    #[test]
    fn test_fts_coverage_pct() {
        let stats = sample_stats();
        let pct = stats.fts_coverage_pct();
        assert!((pct - 90.0).abs() < 0.01); // 450/500 = 90%
    }

    #[test]
    fn test_fts_coverage_pct_zero_documents() {
        let stats = StatsData::default();
        assert_eq!(stats.fts_coverage_pct(), 0.0);
    }

    #[test]
    fn test_has_queue_work() {
        let stats = sample_stats();
        assert!(stats.has_queue_work());
    }

    #[test]
    fn test_no_queue_work() {
        let stats = StatsData {
            queue_pending: 0,
            queue_failed: 0,
            ..sample_stats()
        };
        assert!(!stats.has_queue_work());
    }

    #[test]
    fn test_stats_data_default() {
        let stats = StatsData::default();
        assert_eq!(stats.total_documents, 0);
        assert_eq!(stats.issues, 0);
        assert_eq!(stats.coverage_pct, 0.0);
    }
}
