use std::fmt::{Display, Formatter};

#[derive(
    Debug,
    PartialEq,
    Eq,
    Hash,
    Clone,
    strum::EnumString,
    strum::EnumIter,
    strum::AsRefStr,
    Ord,
    PartialOrd,
)]
#[strum(serialize_all = "snake_case")]
pub enum BackendType {
    Aqua,
    Asdf,
    Cargo,
    Conda,
    Core,
    Dotnet,
    Forgejo,
    Gem,
    Github,
    Gitlab,
    Go,
    Npm,
    Pipx,
    Pkgx,
    Spm,
    Http,
    S3,
    Ubi,
    Vfox,
    VfoxBackend(String),
    Unknown,
}

impl Display for BackendType {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        match self {
            BackendType::VfoxBackend(plugin_name) => write!(formatter, "{plugin_name}"),
            _ => write!(formatter, "{}", format!("{self:?}").to_lowercase()),
        }
    }
}

impl BackendType {
    pub fn disable_key(&self) -> Option<&str> {
        match self {
            BackendType::Unknown => None,
            BackendType::VfoxBackend(plugin_name) => Some(plugin_name),
            _ => Some(self.as_ref()),
        }
    }

    pub fn guess(s: &str) -> BackendType {
        let prefix = s.split(':').next().unwrap_or(s);

        match prefix {
            "aqua" => BackendType::Aqua,
            "asdf" => BackendType::Asdf,
            "cargo" => BackendType::Cargo,
            "conda" => BackendType::Conda,
            "core" => BackendType::Core,
            "dotnet" => BackendType::Dotnet,
            "forgejo" => BackendType::Forgejo,
            "gem" => BackendType::Gem,
            "github" => BackendType::Github,
            "gitlab" => BackendType::Gitlab,
            "go" => BackendType::Go,
            "npm" => BackendType::Npm,
            "pipx" => BackendType::Pipx,
            "pkgx" => BackendType::Pkgx,
            "spm" => BackendType::Spm,
            "http" => BackendType::Http,
            "s3" => BackendType::S3,
            "ubi" => BackendType::Ubi,
            "vfox" => BackendType::Vfox,
            _ => BackendType::Unknown,
        }
    }

    /// Returns true if this backend is still gated behind experimental mode.
    pub fn is_experimental(&self) -> bool {
        use super::{dotnet, pkgx, s3, spm};
        match self {
            BackendType::Dotnet => dotnet::EXPERIMENTAL,
            BackendType::Pkgx => pkgx::EXPERIMENTAL,
            BackendType::S3 => s3::EXPERIMENTAL,
            BackendType::Spm => spm::EXPERIMENTAL,
            _ => false,
        }
    }
}
