//! Error types for PostgreSQL Manager
//!
//! This module provides comprehensive error types for all operations.

use thiserror::Error;

/// Result type alias for PostgreSQL Manager operations
pub type Result<T> = std::result::Result<T, Error>;

/// Error types for PostgreSQL Manager operations
#[derive(Error, Debug)]
pub enum Error {
    /// SSH error
    #[error("SSH error: {0}")]
    Ssh(#[from] lmrc_ssh::Error),

    /// SSH command execution error
    #[error("SSH command execution failed: {message}")]
    SshExecution {
        /// Error message
        message: String,
        /// Command that failed
        command: String,
    },

    /// PostgreSQL installation error
    #[error("PostgreSQL installation failed: {0}")]
    Installation(String),

    /// PostgreSQL configuration error
    #[error("PostgreSQL configuration failed: {0}")]
    Configuration(String),

    /// PostgreSQL not installed
    #[error("PostgreSQL is not installed on the server")]
    NotInstalled,

    /// PostgreSQL already installed
    #[error("PostgreSQL version {0} is already installed")]
    AlreadyInstalled(String),

    /// Invalid PostgreSQL version
    #[error("Invalid PostgreSQL version: {0}")]
    InvalidVersion(String),

    /// Invalid configuration parameter
    #[error("Invalid configuration parameter: {parameter} = {value}")]
    InvalidConfig {
        /// Parameter name
        parameter: String,
        /// Invalid value
        value: String,
    },

    /// Missing required configuration
    #[error("Missing required configuration: {0}")]
    MissingConfig(String),

    /// PostgreSQL service error
    #[error("PostgreSQL service error: {0}")]
    ServiceError(String),

    /// Database connection test failed
    #[error("Database connection test failed: {0}")]
    ConnectionTest(String),

    /// Uninstallation error
    #[error("PostgreSQL uninstallation failed: {0}")]
    Uninstallation(String),

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

    /// Serialization error
    #[error("Serialization error: {0}")]
    Serialization(#[from] serde_json::Error),

    /// Generic error
    #[error("{0}")]
    Other(String),
}

impl Error {
    /// Create a new SSH execution error
    pub fn ssh_execution(message: impl Into<String>, command: impl Into<String>) -> Self {
        Self::SshExecution {
            message: message.into(),
            command: command.into(),
        }
    }

    /// Create a new invalid config error
    pub fn invalid_config(parameter: impl Into<String>, value: impl Into<String>) -> Self {
        Self::InvalidConfig {
            parameter: parameter.into(),
            value: value.into(),
        }
    }
}

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

    #[test]
    fn test_error_display() {
        let err = Error::NotInstalled;
        assert_eq!(err.to_string(), "PostgreSQL is not installed on the server");

        let err = Error::AlreadyInstalled("15".to_string());
        assert_eq!(
            err.to_string(),
            "PostgreSQL version 15 is already installed"
        );

        let err = Error::invalid_config("max_connections", "invalid");
        assert_eq!(
            err.to_string(),
            "Invalid configuration parameter: max_connections = invalid"
        );
    }

    #[test]
    fn test_ssh_execution_error() {
        let err = Error::ssh_execution("command failed", "apt-get install");
        match err {
            Error::SshExecution { message, command } => {
                assert_eq!(message, "command failed");
                assert_eq!(command, "apt-get install");
            }
            _ => panic!("Wrong error type"),
        }
    }
}
