use std::fs;
use std::path::Path;

pub fn collect_md_files(dir: &Path, result: &mut Vec<String>) -> std::io::Result<()> {
    for entry in fs::read_dir(dir)? {
        let entry = entry?;
        let name = entry.file_name();
        if name.to_string_lossy().starts_with('.') {
            continue;
        }
        let path = entry.path();
        if path.is_dir() {
            collect_md_files(&path, result)?;
        } else if path.extension().is_some_and(|e| e == "md") {
            if let Some(s) = path.to_str() {
                result.push(s.to_string());
            }
        }
    }
    Ok(())
}

pub fn read_file(path: &str) -> Result<String, String> {
    fs::read_to_string(path).map_err(|e| e.to_string())
}

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

    fn tmpdir(name: &str) -> PathBuf {
        std::env::temp_dir().join(name)
    }

    #[test]
    fn collect_md_flat() {
        let dir = tmpdir("pena_collect_flat");
        fs::create_dir_all(&dir).unwrap();
        fs::write(dir.join("a.md"), "").unwrap();
        fs::write(dir.join("b.md"), "").unwrap();
        fs::write(dir.join("c.txt"), "").unwrap();
        let mut result = Vec::new();
        collect_md_files(&dir, &mut result).unwrap();
        result.sort();
        fs::remove_dir_all(&dir).unwrap();
        assert_eq!(result.len(), 2);
        assert!(result[0].ends_with("a.md"));
        assert!(result[1].ends_with("b.md"));
    }

    #[test]
    fn collect_md_recursive() {
        let dir = tmpdir("pena_collect_recursive");
        let sub = dir.join("docs");
        fs::create_dir_all(&sub).unwrap();
        fs::write(dir.join("Home.md"), "").unwrap();
        fs::write(sub.join("Page.md"), "").unwrap();
        let mut result = Vec::new();
        collect_md_files(&dir, &mut result).unwrap();
        fs::remove_dir_all(&dir).unwrap();
        assert_eq!(result.len(), 2);
    }

    #[test]
    fn collect_md_ignores_hidden_dir() {
        let dir = tmpdir("pena_collect_hidden_dir");
        let hidden = dir.join(".hidden");
        fs::create_dir_all(&hidden).unwrap();
        fs::write(dir.join("visible.md"), "").unwrap();
        fs::write(hidden.join("secret.md"), "").unwrap();
        let mut result = Vec::new();
        collect_md_files(&dir, &mut result).unwrap();
        fs::remove_dir_all(&dir).unwrap();
        assert_eq!(result.len(), 1);
        assert!(result[0].ends_with("visible.md"));
    }

    #[test]
    fn collect_md_ignores_hidden_file() {
        let dir = tmpdir("pena_collect_hidden_file");
        fs::create_dir_all(&dir).unwrap();
        fs::write(dir.join("visible.md"), "").unwrap();
        fs::write(dir.join(".hidden.md"), "").unwrap();
        let mut result = Vec::new();
        collect_md_files(&dir, &mut result).unwrap();
        fs::remove_dir_all(&dir).unwrap();
        assert_eq!(result.len(), 1);
        assert!(result[0].ends_with("visible.md"));
    }

    #[test]
    fn collect_md_nonexistent_dir() {
        let mut result = Vec::new();
        let err = collect_md_files(Path::new("/nonexistent/path/for/pena"), &mut result);
        assert!(err.is_err());
    }
}
