use crate::config::FormatterConfig;

#[derive(Debug, Clone, Copy)]
pub struct FormatterPresetMetadata {
    pub name: &'static str,
    pub url: &'static str,
    pub description: &'static str,
    pub cmd: &'static str,
    pub args: &'static [&'static str],
    pub stdin: bool,
    pub supported_languages: &'static [&'static str],
}

impl FormatterPresetMetadata {
    pub fn to_formatter_config(self) -> FormatterConfig {
        FormatterConfig {
            cmd: self.cmd.to_string(),
            args: self.args.iter().map(ToString::to_string).collect(),
            enabled: true,
            stdin: self.stdin,
        }
    }
}

const PRESETS: &[FormatterPresetMetadata] = &[
    FormatterPresetMetadata {
        name: "air",
        url: "https://github.com/posit-dev/air",
        description: "R formatter for reproducible style conventions.",
        cmd: "air",
        args: &["format", "{}"],
        stdin: false,
        supported_languages: &["r"],
    },
    FormatterPresetMetadata {
        name: "alejandra",
        url: "https://kamadorueda.com/alejandra/",
        description: "Uncompromising Nix formatter.",
        cmd: "alejandra",
        args: &[],
        stdin: true,
        supported_languages: &["nix"],
    },
    FormatterPresetMetadata {
        name: "asmfmt",
        url: "https://github.com/klauspost/asmfmt",
        description: "Go assembler formatter.",
        cmd: "asmfmt",
        args: &[],
        stdin: true,
        supported_languages: &["asm", "assembly"],
    },
    FormatterPresetMetadata {
        name: "astyle",
        url: "https://astyle.sourceforge.net/astyle.html",
        description: "Formatter for C/C++/Java/C# source code.",
        cmd: "astyle",
        args: &["--quiet"],
        stdin: true,
        supported_languages: &["c", "cpp", "c++", "java", "csharp", "c#"],
    },
    FormatterPresetMetadata {
        name: "autocorrect",
        url: "https://github.com/huacnlee/autocorrect",
        description: "Formatter/linter for CJK spacing and punctuation.",
        cmd: "autocorrect",
        args: &["--stdin"],
        stdin: true,
        supported_languages: &["text", "txt", "markdown", "md"],
    },
    FormatterPresetMetadata {
        name: "bean-format",
        url: "https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format",
        description: "Reformat Beancount files to align posting amounts.",
        cmd: "bean-format",
        args: &["-"],
        stdin: true,
        supported_languages: &["beancount", "bean"],
    },
    FormatterPresetMetadata {
        name: "bibtex-tidy",
        url: "https://github.com/FlamingTempura/bibtex-tidy",
        description: "Cleaner and formatter for BibTeX files.",
        cmd: "bibtex-tidy",
        args: &["--quiet"],
        stdin: true,
        supported_languages: &["bibtex", "bib"],
    },
    FormatterPresetMetadata {
        name: "beautysh",
        url: "https://github.com/lovesegfault/beautysh",
        description: "Bash beautifier for shell scripts.",
        cmd: "beautysh",
        args: &["-"],
        stdin: true,
        supported_languages: &["sh", "bash", "shell"],
    },
    FormatterPresetMetadata {
        name: "black",
        url: "https://github.com/psf/black",
        description: "Opinionated Python formatter.",
        cmd: "black",
        args: &["-"],
        stdin: true,
        supported_languages: &["python", "py"],
    },
    FormatterPresetMetadata {
        name: "clang-format",
        url: "https://clang.llvm.org/docs/ClangFormat.html",
        description: "Formatter for C-family languages.",
        cmd: "clang-format",
        args: &["-"],
        stdin: true,
        supported_languages: &[
            "c",
            "h",
            "cpp",
            "c++",
            "hpp",
            "cc",
            "cxx",
            "rcpp",
            "objc",
            "objective-c",
            "obj-c",
            "java",
            "csharp",
            "c#",
        ],
    },
    FormatterPresetMetadata {
        name: "cmake-format",
        url: "https://github.com/cheshirekow/cmake_format",
        description: "Formatter for CMake listfiles.",
        cmd: "cmake-format",
        args: &["-"],
        stdin: true,
        supported_languages: &["cmake"],
    },
    FormatterPresetMetadata {
        name: "bpfmt",
        url: "https://source.android.com/docs/setup/reference/androidbp",
        description: "Android Blueprint file formatter.",
        cmd: "bpfmt",
        args: &["-w", "{}"],
        stdin: false,
        supported_languages: &["bp", "blueprint"],
    },
    FormatterPresetMetadata {
        name: "bsfmt",
        url: "https://github.com/rokucommunity/brighterscript-formatter",
        description: "Formatter for BrighterScript and BrightScript.",
        cmd: "bsfmt",
        args: &["{}", "--write"],
        stdin: false,
        supported_languages: &["brs", "brighterscript", "brightscript"],
    },
    FormatterPresetMetadata {
        name: "buf",
        url: "https://buf.build/docs/reference/cli/buf/format",
        description: "Formatter for Protocol Buffer files.",
        cmd: "buf",
        args: &["format", "-w", "{}"],
        stdin: false,
        supported_languages: &["proto", "protobuf"],
    },
    FormatterPresetMetadata {
        name: "buildifier",
        url: "https://github.com/bazelbuild/buildtools/tree/main/buildifier",
        description: "Formatter for Bazel BUILD and .bzl files.",
        cmd: "buildifier",
        args: &["-path", "{}", "-"],
        stdin: true,
        supported_languages: &["bazel", "bzl", "starlark"],
    },
    FormatterPresetMetadata {
        name: "cabal-fmt",
        url: "https://hackage.haskell.org/package/cabal-fmt",
        description: "Formatter for Haskell .cabal files.",
        cmd: "cabal-fmt",
        args: &["--inplace", "{}"],
        stdin: false,
        supported_languages: &["cabal", "haskell"],
    },
    FormatterPresetMetadata {
        name: "cljfmt",
        url: "https://github.com/weavejester/cljfmt",
        description: "Detect and fix formatting errors in Clojure code.",
        cmd: "cljfmt",
        args: &["fix", "-"],
        stdin: true,
        supported_languages: &["clojure", "clj", "cljs", "cljc", "edn"],
    },
    FormatterPresetMetadata {
        name: "cue-fmt",
        url: "https://cuelang.org",
        description: "Format CUE files.",
        cmd: "cue",
        args: &["fmt", "-"],
        stdin: true,
        supported_languages: &["cue"],
    },
    FormatterPresetMetadata {
        name: "dfmt",
        url: "https://github.com/dlang-community/dfmt",
        description: "Formatter for D source code.",
        cmd: "dfmt",
        args: &[],
        stdin: true,
        supported_languages: &["d"],
    },
    FormatterPresetMetadata {
        name: "efmt",
        url: "https://github.com/sile/efmt",
        description: "Erlang code formatter.",
        cmd: "efmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["erlang", "erl"],
    },
    FormatterPresetMetadata {
        name: "fish_indent",
        url: "https://fishshell.com/docs/current/cmds/fish_indent.html",
        description: "Indent or prettify fish shell scripts.",
        cmd: "fish_indent",
        args: &[],
        stdin: true,
        supported_languages: &["fish"],
    },
    FormatterPresetMetadata {
        name: "fixjson",
        url: "https://github.com/rhysd/fixjson",
        description: "JSON fixer using relaxed JSON5 parsing.",
        cmd: "fixjson",
        args: &[],
        stdin: true,
        supported_languages: &["json", "json5"],
    },
    FormatterPresetMetadata {
        name: "gdformat",
        url: "https://github.com/Scony/godot-gdscript-toolkit",
        description: "Formatter for Godot GDScript.",
        cmd: "gdformat",
        args: &["-"],
        stdin: true,
        supported_languages: &["gdscript", "gd"],
    },
    FormatterPresetMetadata {
        name: "google-java-format",
        url: "https://github.com/google/google-java-format",
        description: "Reformats Java code to Google Java Style.",
        cmd: "google-java-format",
        args: &["-"],
        stdin: true,
        supported_languages: &["java"],
    },
    FormatterPresetMetadata {
        name: "gleam",
        url: "https://github.com/gleam-lang/gleam",
        description: "Format Gleam source files.",
        cmd: "gleam",
        args: &["format", "--stdin"],
        stdin: true,
        supported_languages: &["gleam"],
    },
    FormatterPresetMetadata {
        name: "gofmt",
        url: "https://pkg.go.dev/cmd/gofmt",
        description: "Go formatter.",
        cmd: "gofmt",
        args: &[],
        stdin: true,
        supported_languages: &["go", "golang"],
    },
    FormatterPresetMetadata {
        name: "gofumpt",
        url: "https://github.com/mvdan/gofumpt",
        description: "Stricter formatting for Go.",
        cmd: "gofumpt",
        args: &[],
        stdin: true,
        supported_languages: &["go", "golang"],
    },
    FormatterPresetMetadata {
        name: "hurlfmt",
        url: "https://hurl.dev/",
        description: "Formatter for Hurl files.",
        cmd: "hurlfmt",
        args: &[],
        stdin: true,
        supported_languages: &["hurl"],
    },
    FormatterPresetMetadata {
        name: "jsonnetfmt",
        url: "https://github.com/google/go-jsonnet",
        description: "Format Jsonnet files.",
        cmd: "jsonnetfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["jsonnet", "libsonnet"],
    },
    FormatterPresetMetadata {
        name: "ktfmt",
        url: "https://github.com/facebook/ktfmt",
        description: "Kotlin formatter for community style conventions.",
        cmd: "ktfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["kotlin", "kt", "kts"],
    },
    FormatterPresetMetadata {
        name: "leptosfmt",
        url: "https://github.com/bram209/leptosfmt",
        description: "Formatter for Leptos `view!` macro code.",
        cmd: "leptosfmt",
        args: &["--stdin"],
        stdin: true,
        supported_languages: &["rust", "rs"],
    },
    FormatterPresetMetadata {
        name: "mdformat",
        url: "https://github.com/executablebooks/mdformat",
        description: "Opinionated Markdown formatter.",
        cmd: "mdformat",
        args: &["-"],
        stdin: true,
        supported_languages: &["md", "markdown", "qmd", "rmd"],
    },
    FormatterPresetMetadata {
        name: "nixfmt",
        url: "https://github.com/NixOS/nixfmt",
        description: "Official formatter for Nix code.",
        cmd: "nixfmt",
        args: &[],
        stdin: true,
        supported_languages: &["nix"],
    },
    FormatterPresetMetadata {
        name: "nginxfmt",
        url: "https://github.com/slomkowski/nginx-config-formatter",
        description: "Formatter for nginx configuration files.",
        cmd: "nginxfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["nginx", "nginxconf"],
    },
    FormatterPresetMetadata {
        name: "prettier",
        url: "https://prettier.io/",
        description: "Opinionated formatter for web, JSON, YAML, and Markdown ecosystems.",
        cmd: "prettier",
        args: &["--stdin-filepath", "{}"],
        stdin: true,
        supported_languages: &[
            "javascript",
            "js",
            "typescript",
            "ts",
            "jsx",
            "tsx",
            "json",
            "jsonc",
            "yaml",
            "yml",
            "markdown",
            "md",
            "css",
            "scss",
            "less",
            "html",
            "vue",
            "svelte",
            "graphql",
            "gql",
        ],
    },
    FormatterPresetMetadata {
        name: "pycln",
        url: "https://github.com/hadialqattan/pycln",
        description: "Removes unused Python imports.",
        cmd: "pycln",
        args: &["--silence", "-"],
        stdin: true,
        supported_languages: &["python", "py"],
    },
    FormatterPresetMetadata {
        name: "pyproject-fmt",
        url: "https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt",
        description: "Formatter for pyproject.toml with comment support.",
        cmd: "pyproject-fmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["toml"],
    },
    FormatterPresetMetadata {
        name: "racketfmt",
        url: "https://docs.racket-lang.org/fmt",
        description: "Formatter for Racket language files.",
        cmd: "raco",
        args: &["fmt"],
        stdin: true,
        supported_languages: &["racket", "rkt"],
    },
    FormatterPresetMetadata {
        name: "rubyfmt",
        url: "https://github.com/fables-tales/rubyfmt",
        description: "Ruby autoformatter written in Rust.",
        cmd: "rubyfmt",
        args: &[],
        stdin: true,
        supported_languages: &["ruby", "rb"],
    },
    FormatterPresetMetadata {
        name: "ruff",
        url: "https://docs.astral.sh/ruff/",
        description: "Python formatter via Ruff.",
        cmd: "ruff",
        args: &["format", "--stdin-filename", "stdin.py", "-"],
        stdin: true,
        supported_languages: &["python", "py"],
    },
    FormatterPresetMetadata {
        name: "rufo",
        url: "https://github.com/ruby-formatter/rufo",
        description: "Opinionated Ruby formatter.",
        cmd: "rufo",
        args: &[],
        stdin: true,
        supported_languages: &["ruby", "rb"],
    },
    FormatterPresetMetadata {
        name: "shfmt",
        url: "https://github.com/mvdan/sh",
        description: "Shell script formatter.",
        cmd: "shfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["sh", "bash", "zsh", "ksh", "shell"],
    },
    FormatterPresetMetadata {
        name: "sqlfmt",
        url: "https://sqlfmt.com",
        description: "SQL formatter inspired by Black.",
        cmd: "sqlfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["sql"],
    },
    FormatterPresetMetadata {
        name: "styler",
        url: "https://styler.r-lib.org/",
        description: "R formatter via styler::style_file.",
        cmd: "Rscript",
        args: &["-e", "styler::style_file('{}')"],
        stdin: false,
        supported_languages: &["r"],
    },
    FormatterPresetMetadata {
        name: "taplo",
        url: "https://taplo.tamasfe.dev/",
        description: "TOML formatter.",
        cmd: "taplo",
        args: &["format", "-"],
        stdin: true,
        supported_languages: &["toml"],
    },
    FormatterPresetMetadata {
        name: "tclfmt",
        url: "https://github.com/nmoroze/tclint",
        description: "Formatter for Tcl scripts (from tclint).",
        cmd: "tclfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["tcl"],
    },
    FormatterPresetMetadata {
        name: "tex-fmt",
        url: "https://github.com/WGUNDERWOOD/tex-fmt",
        description: "Fast formatter for LaTeX source files.",
        cmd: "tex-fmt",
        args: &["-s"],
        stdin: true,
        supported_languages: &["tex", "latex"],
    },
    FormatterPresetMetadata {
        name: "terraform-fmt",
        url: "https://developer.hashicorp.com/terraform/cli/commands/fmt",
        description: "Terraform formatter.",
        cmd: "terraform",
        args: &["fmt", "-no-color", "-"],
        stdin: true,
        supported_languages: &["terraform", "hcl", "tf"],
    },
    FormatterPresetMetadata {
        name: "typstyle",
        url: "https://github.com/Enter-tainer/typstyle",
        description: "Formatter for Typst code.",
        cmd: "typstyle",
        args: &[],
        stdin: true,
        supported_languages: &["typst"],
    },
    FormatterPresetMetadata {
        name: "yamlfmt",
        url: "https://github.com/google/yamlfmt",
        description: "YAML formatter.",
        cmd: "yamlfmt",
        args: &["-"],
        stdin: true,
        supported_languages: &["yaml", "yml"],
    },
    FormatterPresetMetadata {
        name: "yamlfix",
        url: "https://github.com/lyz-code/yamlfix",
        description: "YAML formatter preserving comments.",
        cmd: "yamlfix",
        args: &["-"],
        stdin: true,
        supported_languages: &["yaml", "yml"],
    },
    FormatterPresetMetadata {
        name: "yq",
        url: "https://github.com/mikefarah/yq",
        description: "YAML processor in pretty-print mode.",
        cmd: "yq",
        args: &["-P", "-"],
        stdin: true,
        supported_languages: &["yaml", "yml"],
    },
];

pub fn formatter_preset_metadata(name: &str) -> Option<&'static FormatterPresetMetadata> {
    PRESETS.iter().find(|preset| preset.name == name)
}

pub fn all_formatter_preset_metadata() -> &'static [FormatterPresetMetadata] {
    PRESETS
}

pub fn formatter_presets_for_language(language: &str) -> Vec<&'static FormatterPresetMetadata> {
    let normalized = language.trim().to_ascii_lowercase().replace('_', "-");
    PRESETS
        .iter()
        .filter(|preset| {
            preset
                .supported_languages
                .iter()
                .any(|supported| *supported == normalized)
        })
        .collect()
}

pub fn get_formatter_preset(name: &str) -> Option<FormatterConfig> {
    formatter_preset_metadata(name)
        .copied()
        .map(|meta| meta.to_formatter_config())
}

pub fn formatter_preset_supported_languages(name: &str) -> Option<&'static [&'static str]> {
    formatter_preset_metadata(name).map(|meta| meta.supported_languages)
}

pub fn formatter_preset_names() -> &'static [&'static str] {
    &[
        "air",
        "alejandra",
        "asmfmt",
        "astyle",
        "autocorrect",
        "bean-format",
        "bibtex-tidy",
        "beautysh",
        "black",
        "bpfmt",
        "bsfmt",
        "buf",
        "buildifier",
        "cabal-fmt",
        "clang-format",
        "cljfmt",
        "cmake-format",
        "cue-fmt",
        "dfmt",
        "efmt",
        "fish_indent",
        "fixjson",
        "gdformat",
        "google-java-format",
        "gleam",
        "gofmt",
        "gofumpt",
        "hurlfmt",
        "jsonnetfmt",
        "ktfmt",
        "leptosfmt",
        "mdformat",
        "nixfmt",
        "nginxfmt",
        "prettier",
        "pycln",
        "pyproject-fmt",
        "racketfmt",
        "rubyfmt",
        "ruff",
        "rufo",
        "shfmt",
        "sqlfmt",
        "styler",
        "tclfmt",
        "taplo",
        "tex-fmt",
        "terraform-fmt",
        "typstyle",
        "yamlfix",
        "yamlfmt",
        "yq",
    ]
}

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

    #[test]
    fn clang_format_is_available_for_rcpp_language() {
        let presets = formatter_presets_for_language("Rcpp");
        assert!(
            presets.iter().any(|preset| preset.name == "clang-format"),
            "Expected clang-format preset to support Rcpp"
        );
    }
}
