use thiserror::Error;

pub type Result<T> = std::result::Result<T, DbnestError>;

#[derive(Debug, Error)]
pub enum DbnestError {
    #[error("invalid argument: {0}")]
    InvalidArgument(String),

    #[error("instance not found: {0}")]
    InstanceNotFound(String),

    #[error("docker not available (required for postgres/mysql in v1)")]
    DockerNotAvailable,

    #[error("io error: {0}")]
    Io(#[from] std::io::Error),

    #[error("json error: {0}")]
    Json(#[from] serde_json::Error),

    #[error("docker command failed\ncommand: {command}\nstderr: {stderr}\nhint: {hint}")]
    DockerCommandFailed {
        command: String,
        stderr: String,
        hint: String,
    },
}

impl DbnestError {
    pub fn kind(&self) -> &'static str {
        match self {
            Self::InvalidArgument(_) => "invalid_argument",
            Self::InstanceNotFound(_) => "instance_not_found",
            Self::DockerNotAvailable => "docker_not_available",
            Self::Io(_) => "io",
            Self::Json(_) => "json",
            Self::DockerCommandFailed { .. } => "docker_command_failed",
        }
    }
}
