use std::path::Path;

use tracing::{info, warn};

use super::{ANALYSIS_INPUT_FILE, AnalyzeJob, AnalyzeSender, DOCUMENT_FILE};

/// Walk `data_path/*/` and enqueue every pending analysis for every user.
/// Intended to run once at startup; the same primitive backs the per-user
/// self-heal triggered by web handlers.
pub async fn scan_and_enqueue(data_path: &Path, tx: &AnalyzeSender) {
    let Ok(mut users) = tokio::fs::read_dir(data_path).await else {
        return;
    };
    let mut total = 0;
    while let Ok(Some(user_entry)) = users.next_entry().await {
        total += enqueue_pending_for_user(&user_entry.path(), tx).await;
    }
    info!(count = total, "Analyze recovery scan finished");
}

/// Scan a user's case dirs and enqueue any case that has an
/// `analysis_input.json` but no `document.md`. Returns the number sent.
pub async fn enqueue_pending_for_user(user_root: &Path, tx: &AnalyzeSender) -> usize {
    let Ok(mut cases) = tokio::fs::read_dir(user_root).await else {
        return 0;
    };
    let mut sent = 0;
    while let Ok(Some(case_entry)) = cases.next_entry().await {
        let case_dir = case_entry.path();
        if !case_dir.is_dir() || crate::paths::is_closed(&case_dir).await {
            continue;
        }
        if !case_dir.join(ANALYSIS_INPUT_FILE).exists() {
            continue;
        }
        if case_dir.join(DOCUMENT_FILE).exists() {
            continue;
        }
        if tx
            .send(AnalyzeJob {
                case_dir: case_dir.clone(),
            })
            .is_err()
        {
            warn!(case = %case_dir.display(), "recovery send failed (worker gone)");
            return sent;
        }
        sent += 1;
    }
    sent
}
