use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum BtrfsError {
    CommandFailed(String),
    InvalidPath(String),
    QuotaError(String),
    ParseError(String),
    IOError(std::io::Error),
    MountFailed(String),
    UnmountFailed(String),
    FormatFailed(String),
    DeviceError(String),
    AlreadyMounted(String),
    NotMounted(String),
    QuotaNotEnabled(String),
    InvalidDevice(String),
}

impl fmt::Display for BtrfsError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            BtrfsError::CommandFailed(msg) => write!(f, "Btrfs command failed: {}", msg),
            BtrfsError::InvalidPath(msg) => write!(f, "Invalid path: {}", msg),
            BtrfsError::QuotaError(msg) => write!(f, "Quota error: {}", msg),
            BtrfsError::ParseError(msg) => write!(f, "Parse error: {}", msg),
            BtrfsError::IOError(e) => write!(f, "IO error: {}", e),
            BtrfsError::MountFailed(msg) => write!(f, "Mount failed: {}", msg),
            BtrfsError::UnmountFailed(msg) => write!(f, "Unmount failed: {}", msg),
            BtrfsError::FormatFailed(msg) => write!(f, "Format failed: {}", msg),
            BtrfsError::DeviceError(msg) => write!(f, "Device error: {}", msg),
            BtrfsError::AlreadyMounted(msg) => write!(f, "Filesystem already mounted: {}", msg),
            BtrfsError::NotMounted(msg) => write!(f, "Filesystem not mounted: {}", msg),
            BtrfsError::QuotaNotEnabled(msg) => write!(f, "Quota not enabled: {}", msg),
            BtrfsError::InvalidDevice(msg) => write!(f, "Invalid device: {}", msg),
        }
    }
}

impl Error for BtrfsError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            BtrfsError::IOError(e) => Some(e),
            _ => None,
        }
    }
}

impl From<std::io::Error> for BtrfsError {
    fn from(error: std::io::Error) -> Self {
        BtrfsError::IOError(error)
    }
}
