use std::sync::Arc;

use thiserror::Error;

/// Errors that can occur during file reconstruction.
#[non_exhaustive]
#[derive(Error, Debug, Clone)]
pub enum FileReconstructionError {
    #[error("CAS Client Error: {0}")]
    ClientError(Arc<xet_client::ClientError>),

    #[error("IO Error: {0}")]
    IoError(Arc<std::io::Error>),

    #[error("Task Runtime Error: {0}")]
    TaskRuntimeError(Arc<xet_runtime::utils::RwTaskLockError>),

    #[error("Corrupted Reconstruction: {0}")]
    CorruptedReconstruction(String),

    #[error("Configuration Error: {0}")]
    ConfigurationError(String),

    #[error("Internal Writer Error: {0}")]
    InternalWriterError(String),

    #[error("Internal Error: {0}")]
    InternalError(String),

    #[error("Task Join Error: {0}")]
    TaskJoinError(Arc<tokio::task::JoinError>),

    #[cfg(target_family = "wasm")]
    #[error("Task Join Error (wasm): {0}")]
    WasmTaskJoinError(Arc<tokio_with_wasm::task::JoinError>),

    #[error("Runtime Error: {0}")]
    RuntimeError(Arc<xet_runtime::RuntimeError>),
}

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

impl From<std::io::Error> for FileReconstructionError {
    fn from(err: std::io::Error) -> Self {
        FileReconstructionError::IoError(Arc::new(err))
    }
}

impl From<xet_client::ClientError> for FileReconstructionError {
    fn from(err: xet_client::ClientError) -> Self {
        FileReconstructionError::ClientError(Arc::new(err))
    }
}

impl From<xet_runtime::utils::RwTaskLockError> for FileReconstructionError {
    fn from(err: xet_runtime::utils::RwTaskLockError) -> Self {
        FileReconstructionError::TaskRuntimeError(Arc::new(err))
    }
}

impl From<tokio::task::JoinError> for FileReconstructionError {
    fn from(err: tokio::task::JoinError) -> Self {
        FileReconstructionError::TaskJoinError(Arc::new(err))
    }
}

#[cfg(target_family = "wasm")]
impl From<tokio_with_wasm::task::JoinError> for FileReconstructionError {
    fn from(err: tokio_with_wasm::task::JoinError) -> Self {
        FileReconstructionError::WasmTaskJoinError(Arc::new(err))
    }
}

impl From<xet_runtime::RuntimeError> for FileReconstructionError {
    fn from(err: xet_runtime::RuntimeError) -> Self {
        FileReconstructionError::RuntimeError(Arc::new(err))
    }
}
