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

pub type QueryResult<T> = Result<T, QueryError>;

#[derive(Debug)]
pub enum QueryError {
    DbDriverError(tokio_postgres::Error),
    UnexpectedRowCount { expected: usize, actual: u64 },
}

impl fmt::Display for QueryError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        return match self {
            QueryError::DbDriverError(e) => e.fmt(f),
            QueryError::UnexpectedRowCount { expected, actual } => {
                write!(f, "Expected {expected} rows to be affected, got {actual}")
            }
        };
    }
}

impl Error for QueryError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        return match self {
            QueryError::DbDriverError(ref e) => Some(e),
            QueryError::UnexpectedRowCount { .. } => None,
        };
    }
}

impl From<tokio_postgres::Error> for QueryError {
    fn from(err: tokio_postgres::Error) -> Self {
        return QueryError::DbDriverError(err);
    }
}
