//! Errors that are captured for artifact release related actions.

use radicle::{cob, git};
use thiserror::Error;

use crate::Cid;

/// Errors that can occur when looking up a [`Release`][release] by commit OID.
///
/// [release]: super::Release
#[derive(Debug, Error)]
pub enum FindRelease {
    /// No release was found for the given commit.
    #[error("no release found for commit {0}")]
    NoRelease(git::Oid),
    /// Multiple releases were found for the given commit.
    #[error("multiple releases found for commit {0}")]
    Ambiguous(git::Oid),
    /// An error occurred in the underlying COB store.
    #[error("failed to look up release for commit {oid}")]
    Store {
        /// The commit OID being looked up.
        oid: git::Oid,
        /// The underlying store error.
        #[source]
        err: cob::store::Error,
    },
}

/// Errors that can occur when redacting an artifact.
#[derive(Debug, Error)]
pub enum Redact {
    /// The artifact CID was not found in the release.
    #[error("artifact {cid} not found in release")]
    NotFound {
        /// The CID that was not found.
        cid: Cid,
    },
    /// The redaction reason exceeds the maximum allowed length.
    #[error("redaction reason exceeds maximum length of {max} bytes (got {actual})")]
    ReasonTooLong {
        /// The actual byte length of the reason.
        actual: usize,
        /// The maximum allowed byte length.
        max: usize,
    },
    /// An error occurred in the underlying COB store.
    #[error(transparent)]
    Store(#[from] cob::store::Error),
}

/// Errors that can occur when building a [`Release`][release].
///
/// [release]: super::Release
#[derive(Debug, Error)]
pub enum Build {
    /// The initial action in the history of the [`Release`][release] was not a
    /// [`Create`][create].
    ///
    /// [release]: super::Release
    /// [create]: super::Action::Create
    #[error("initial action of release must create with an OID")]
    Initial,
    /// The [`Create`][create] referred to a commit that could not be found.
    ///
    /// [create]: super::Action::Create
    #[error("missing commit for release {oid}: {err}")]
    MissingCommit {
        /// The [`Oid`][oid] of the commit that was requested, but is missing.
        ///
        /// [oid]: git::Oid
        oid: git::Oid,
        /// The underlying error from Git that occurred.
        #[source]
        err: git::raw::Error,
    },
}

/// Errors that can occur when applying an [`Entry`][entry] to the [`Release`][release]
/// collaborative object.
///
/// [entry]: radicle::cob::Entry
/// [release]: super::Release
#[derive(Debug, Error)]
pub enum Apply {
    /// Applying the entry resulted in a [`Build`] error.
    #[error(transparent)]
    Build(#[from] Build),
    /// Error occurred when decoding an [`Entry`][entry] into an [`Op`][op].
    ///
    /// [entry]: radicle::cob::Entry
    /// [op]: radicle::cob::Op
    #[error(transparent)]
    Op(#[from] cob::op::OpEncodingError),
}
