use panache::config::{Extensions, Flavor};
use panache::{Config, format};
use std::collections::HashMap;

#[test]
fn code_block_with_shfmt() {
    // Skip if shfmt not available
    if which::which("shfmt").is_err() {
        println!("Skipping shfmt test - shfmt not installed");
        return;
    }

    let mut formatters = HashMap::new();
    formatters.insert(
        "sh".to_string(),
        vec![panache::config::FormatterConfig {
            cmd: "shfmt".to_string(),
            args: vec![],
            enabled: true,
            stdin: true,
        }],
    );

    let config = Config {
        formatters,
        ..Default::default()
    };

    let input = r#"
```sh
if true; then echo ok; fi
```
"#
    .trim_start();

    let output = format(input, Some(config), None);

    // shfmt should format the shell code (expands one-liner)
    assert!(output.contains("```sh"));
    assert!(output.contains("if true; then"));
}

#[test]
fn code_block_with_external_formatter() {
    // Use 'tr' to uppercase as a simple mock formatter
    let mut formatters = HashMap::new();
    formatters.insert(
        "test".to_string(),
        vec![panache::config::FormatterConfig {
            cmd: "tr".to_string(),
            args: vec!["[:lower:]".to_string(), "[:upper:]".to_string()],
            enabled: true,
            stdin: true,
        }],
    );

    let config = Config {
        formatters,
        ..Default::default()
    };

    let input = r#"
```test
hello world
```
"#
    .trim_start();

    let output = format(input, Some(config), None);

    // Code should be uppercased by the formatter
    assert!(output.contains("HELLO WORLD"));
    assert!(output.contains("```test"));
    assert!(output.contains("```\n"));
}

#[test]
fn code_block_without_formatter_unchanged() {
    // Create config with empty formatters (no built-in defaults)
    let config = Config {
        formatters: HashMap::new(),
        ..Default::default()
    };

    let input = r#"
```python
hello world
```
"#
    .trim_start();

    let output = format(input, Some(config), None);

    // Code should be unchanged (no formatter configured)
    assert!(output.contains("hello world"));
    assert!(!output.contains("HELLO WORLD"));
}

#[test]
fn code_block_with_disabled_formatter() {
    // In the new format, disabled formatters are handled by not including them in the map
    // This test now verifies that an empty formatter list means no formatting
    let formatters = HashMap::new(); // No formatter configured

    let config = Config {
        formatters,
        ..Default::default()
    };

    let input = r#"
```test
hello world
```
"#
    .trim_start();

    let output = format(input, Some(config), None);

    // Code should be unchanged (no formatter configured)
    assert!(output.contains("hello world"));
    assert!(!output.contains("HELLO WORLD"));
}

#[test]
fn code_block_with_failing_formatter() {
    let mut formatters = HashMap::new();
    formatters.insert(
        "test".to_string(),
        vec![panache::config::FormatterConfig {
            cmd: "false".to_string(), // Always fails
            args: vec![],
            enabled: true,
            stdin: true,
        }],
    );

    let config = Config {
        formatters,
        ..Default::default()
    };

    let input = r#"
```test
hello world
```
"#
    .trim_start();

    let output = format(input, Some(config), None);

    // Code should be unchanged on formatter failure
    assert!(output.contains("hello world"));
    assert!(!output.contains("HELLO WORLD"));
}

#[test]
fn python_hashpipe_prefix_preserved_with_external_formatter() {
    let mut formatters = HashMap::new();
    formatters.insert(
        "python".to_string(),
        vec![panache::config::FormatterConfig {
            cmd: "tr".to_string(),
            args: vec!["[:lower:]".to_string(), "[:upper:]".to_string()],
            enabled: true,
            stdin: true,
        }],
    );

    let flavor = Flavor::Quarto;
    let config = Config {
        flavor,
        extensions: Extensions::for_flavor(flavor),
        formatters,
        ..Default::default()
    };

    let input = r#"
```{python}
#| label: setup
#| fig-cap: "My figure"

print("ok")
```
"#
    .trim_start();

    let output = format(input, Some(config), None);

    assert!(output.contains("#| label: setup"));
    assert!(output.contains("#| fig-cap: \"My figure\""));
    assert!(output.contains("PRINT(\"OK\")"));
    assert!(!output.contains("# |"));
}
