use std::io;
use std::path::PathBuf;
use deadpool_postgres::tokio_postgres::Error as TokioPostgresError;
use deadpool_postgres::tokio_postgres::config::SslMode;
use deadpool_postgres::{BuildError, PoolError};
use martin_tile_utils::TileCoord;
use semver::Version;
use crate::tiles::UrlQuery;
use crate::tiles::postgres::utils::query_to_json;
pub type PostgresResult<T> = Result<T, PostgresError>;
#[non_exhaustive]
#[derive(thiserror::Error, Debug)]
pub enum PostgresError {
#[error("Cannot load platform root certificates: {0:?}")]
CannotLoadRoots(Vec<rustls_native_certs::Error>),
#[error("Cannot open certificate file {1}: {0}")]
CannotOpenCert(#[source] io::Error, PathBuf),
#[error("Cannot parse certificate file {1}: {0}")]
CannotParseCert(#[source] io::Error, PathBuf),
#[error("Unable to parse PEM RSA key file {0}")]
InvalidPrivateKey(PathBuf),
#[error("Unable to use client certificate pair {1} / {2}: {0}")]
CannotUseClientKey(#[source] rustls::Error, PathBuf, PathBuf),
#[error(transparent)]
RustlsError(#[from] rustls::Error),
#[error("Unknown SSL mode: {0:?}")]
UnknownSslMode(SslMode),
#[error("Postgres error while {1}: {0}")]
PostgresError(#[source] TokioPostgresError, &'static str),
#[error("Unable to build a Postgres connection pool {1}: {0}")]
PostgresPoolBuildError(#[source] BuildError, String),
#[error("Unable to get a Postgres connection from the pool {1}: {0}")]
PostgresPoolConnError(#[source] PoolError, String),
#[error("Unable to parse connection string {1}: {0}")]
BadConnectionString(#[source] TokioPostgresError, String),
#[error("Unable to parse PostGIS version {1}: {0}")]
BadPostgisVersion(#[source] semver::Error, String),
#[error("Unable to parse PostgreSQL version {1}: {0}")]
BadPostgresVersion(#[source] semver::Error, String),
#[error("PostGIS version {0} is too old, minimum required is {1}")]
PostgisTooOld(Version, Version),
#[error("PostgreSQL version {0} is too old, minimum required is {1}")]
PostgresqlTooOld(Version, Version),
#[error("Invalid extent setting in source {0} for table {1}: extent=0")]
InvalidTableExtent(String, String),
#[error("Error preparing a query for the tile '{1}' ({2}): {3} {0}")]
PrepareQueryError(#[source] TokioPostgresError, String, String, String),
#[error(r"Unable to get tile {2:#} from {1}: {0}")]
GetTileError(#[source] TokioPostgresError, String, TileCoord),
#[error(r"Unable to get tile {2:#} with {json_query:?} params from {1}: {0}", json_query=query_to_json(.3.as_ref()))]
GetTileWithQueryError(
#[source] TokioPostgresError,
String,
TileCoord,
Option<UrlQuery>,
),
}