use crate::application::{file_service, render_service};
use crate::infrastructure::comrak_renderer::{
    syntax_css_for_theme, ComrakPreviewRenderer, ComrakRenderer,
};

#[tauri::command]
pub fn render_markdown(content: String) -> String {
    let renderer = ComrakPreviewRenderer;
    render_service::render_string(&renderer, &content)
}

#[tauri::command]
pub fn convert_file(path: String) -> Result<String, String> {
    let renderer = ComrakRenderer;
    render_service::render_file(&renderer, &path)
}

#[tauri::command]
pub fn get_syntax_highlight_css() -> String {
    syntax_css_for_theme("base16-ocean.dark")
}

#[tauri::command]
pub fn list_md_files(dir: String) -> Result<Vec<String>, String> {
    file_service::list_markdown_files(&dir)
}

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

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

    #[test]
    fn render_markdown_heading() {
        let html = render_markdown("# Hello\n".to_string());
        assert!(html.contains("<h1>"));
        assert!(html.contains("Hello"));
    }

    #[test]
    fn render_markdown_code_block() {
        let html = render_markdown("```rust\nfn main() {}\n```\n".to_string());
        assert!(html.contains("syntax-highlighting"));
    }

    #[test]
    fn render_markdown_empty() {
        let html = render_markdown(String::new());
        assert!(!html.contains("<h1>"));
    }

    #[test]
    fn convert_file_success() {
        let dir = tmpdir("pena_convert_success");
        fs::create_dir_all(&dir).unwrap();
        let file = dir.join("test.md");
        fs::write(&file, "# Title\n\nParagraph.").unwrap();
        let result = convert_file(file.to_string_lossy().to_string());
        fs::remove_dir_all(&dir).unwrap();
        assert!(result.is_ok());
        assert!(result.unwrap().contains("<h1>"));
    }

    #[test]
    fn convert_file_with_table() {
        let dir = tmpdir("pena_convert_table");
        fs::create_dir_all(&dir).unwrap();
        let file = dir.join("table.md");
        fs::write(&file, "| A | B |\n|---|---|\n| 1 | 2 |").unwrap();
        let result = convert_file(file.to_string_lossy().to_string());
        fs::remove_dir_all(&dir).unwrap();
        assert!(result.is_ok());
        assert!(result.unwrap().contains("<table>"));
    }

    #[test]
    fn convert_file_not_found() {
        let result = convert_file("/nonexistent/path/does/not/exist.md".to_string());
        assert!(result.is_err());
    }

    #[test]
    fn get_syntax_highlight_css_returns_non_empty() {
        let css = get_syntax_highlight_css();
        assert!(!css.is_empty());
    }

    #[test]
    fn get_syntax_highlight_css_contains_wrapper_class() {
        let css = get_syntax_highlight_css();
        assert!(css.contains(".syntax-highlighting {"));
    }

    #[test]
    fn list_md_files_sorted() {
        let dir = tmpdir("pena_list_sorted");
        fs::create_dir_all(&dir).unwrap();
        fs::write(dir.join("z.md"), "").unwrap();
        fs::write(dir.join("a.md"), "").unwrap();
        fs::write(dir.join("m.md"), "").unwrap();
        let result = list_md_files(dir.to_string_lossy().to_string()).unwrap();
        fs::remove_dir_all(&dir).unwrap();
        assert_eq!(result.len(), 3);
        assert!(result[0] < result[1] && result[1] < result[2]);
    }

    #[test]
    fn list_md_files_not_a_dir() {
        let result = list_md_files("/nonexistent/does/not/exist".to_string());
        assert!(result.is_err());
    }
}
