use anyhow::Result;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use serde_json;

/// Rebuild index.json files for all collections in content directory
pub fn run(content_dir: &Path) -> Result<()> {
    if !content_dir.exists() {
        println!("Content directory not found: {}", content_dir.display());
        return Ok(());
    }

    let mut total_updated = 0;
    let mut total_created = 0;

    // Iterate through DID directories
    for did_entry in fs::read_dir(content_dir)? {
        let did_entry = did_entry?;
        let did_path = did_entry.path();

        if !did_path.is_dir() {
            continue;
        }

        let did_name = did_path.file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("");

        // Skip non-DID directories
        if !did_name.starts_with("did:") {
            continue;
        }

        // Iterate through collection directories
        for col_entry in fs::read_dir(&did_path)? {
            let col_entry = col_entry?;
            let col_path = col_entry.path();

            if !col_path.is_dir() {
                continue;
            }

            let col_name = col_path.file_name()
                .and_then(|n| n.to_str())
                .unwrap_or("");

            // Collect all rkeys from .json files (excluding special files)
            let mut rkeys: Vec<String> = Vec::new();
            let mut rkey_dates: HashMap<String, String> = HashMap::new();

            for file_entry in fs::read_dir(&col_path)? {
                let file_entry = file_entry?;
                let file_path = file_entry.path();

                if !file_path.is_file() {
                    continue;
                }

                let filename = file_path.file_name()
                    .and_then(|n| n.to_str())
                    .unwrap_or("");

                // Skip non-json and special files
                if !filename.ends_with(".json") {
                    continue;
                }
                if filename == "index.json" || filename == "describe.json" || filename == "self.json" {
                    continue;
                }

                // Extract rkey from filename
                let rkey = filename.trim_end_matches(".json").to_string();

                // Read publishedAt from JSON for chronological sorting
                if let Ok(content) = fs::read_to_string(&file_path) {
                    if let Ok(json) = serde_json::from_str::<serde_json::Value>(&content) {
                        if let Some(date) = json.pointer("/value/publishedAt")
                            .or_else(|| json.get("publishedAt"))
                            .and_then(|v| v.as_str())
                        {
                            rkey_dates.insert(rkey.clone(), date.to_string());
                        }
                    }
                }

                rkeys.push(rkey);
            }

            if rkeys.is_empty() {
                continue;
            }

            // Sort by publishedAt (oldest first), fallback to rkey string comparison
            rkeys.sort_by(|a, b| {
                match (rkey_dates.get(a), rkey_dates.get(b)) {
                    (Some(da), Some(db)) => da.cmp(db),
                    (Some(_), None) => std::cmp::Ordering::Less,
                    (None, Some(_)) => std::cmp::Ordering::Greater,
                    (None, None) => a.cmp(b),
                }
            });

            // Check existing index.json
            let index_path = col_path.join("index.json");
            let existing: Vec<String> = if index_path.exists() {
                fs::read_to_string(&index_path)
                    .ok()
                    .and_then(|s| serde_json::from_str(&s).ok())
                    .unwrap_or_default()
            } else {
                Vec::new()
            };

            // Compare and update if different
            if existing != rkeys {
                fs::write(&index_path, serde_json::to_string_pretty(&rkeys)?)?;

                if existing.is_empty() && !index_path.exists() {
                    println!("  Created: {}/{}/index.json ({} records)", did_name, col_name, rkeys.len());
                    total_created += 1;
                } else {
                    println!("  Updated: {}/{}/index.json ({} -> {} records)",
                        did_name, col_name, existing.len(), rkeys.len());
                    total_updated += 1;
                }
            }
        }
    }

    if total_created == 0 && total_updated == 0 {
        println!("All index.json files are up to date.");
    } else {
        println!("\nDone: {} created, {} updated", total_created, total_updated);
    }

    Ok(())
}
