//! Error types for host-product-view.

/// Errors that can occur when dispatching delegate callbacks or managing
/// product view lifecycle.
#[derive(Debug, thiserror::Error)]
pub enum ProductError {
    /// The product ID supplied by the caller was not recognised.
    #[error("unknown product id: {0}")]
    UnknownProduct(String),

    /// The delegate rejected a response payload (e.g. invalid encoding).
    #[error("response rejected: {0}")]
    ResponseRejected(String),

    /// A sign request could not be fulfilled (key not found, user cancelled, etc.).
    #[error("sign failed: {0}")]
    SignFailed(String),

    /// A chain RPC dispatch failed at the delegate layer.
    #[error("chain rpc failed: {0}")]
    ChainRpcFailed(String),

    /// A chain subscription could not be started or delivered.
    #[error("chain subscription failed: {0}")]
    ChainSubscriptionFailed(String),

    /// A chain follow subscription could not be started.
    #[error("chain follow failed: {0}")]
    ChainFollowFailed(String),

    /// A navigation request was rejected by the host.
    #[error("navigate rejected: {0}")]
    NavigateRejected(String),

    /// The product assets could not be loaded (e.g. network error, missing CAR).
    #[error("asset load failed: {0}")]
    AssetLoadFailed(String),
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_error_display_messages() {
        let cases = vec![
            (
                ProductError::UnknownProduct("foo".into()),
                "unknown product id: foo",
            ),
            (
                ProductError::ResponseRejected("bad".into()),
                "response rejected: bad",
            ),
            (
                ProductError::SignFailed("cancelled".into()),
                "sign failed: cancelled",
            ),
            (
                ProductError::ChainRpcFailed("timeout".into()),
                "chain rpc failed: timeout",
            ),
            (
                ProductError::ChainSubscriptionFailed("no chain".into()),
                "chain subscription failed: no chain",
            ),
            (
                ProductError::ChainFollowFailed("gone".into()),
                "chain follow failed: gone",
            ),
            (
                ProductError::NavigateRejected("blocked".into()),
                "navigate rejected: blocked",
            ),
            (
                ProductError::AssetLoadFailed("404".into()),
                "asset load failed: 404",
            ),
        ];
        for (err, expected) in cases {
            assert_eq!(err.to_string(), expected);
        }
    }
}
