//! Error types for Synor Compute.

use crate::{JobId, NodeId, ProcessorId, ProcessorType};
use thiserror::Error;

/// Compute errors.
#[derive(Debug, Error)]
pub enum ComputeError {
    /// Job not found.
    #[error("Job not found: {0}")]
    JobNotFound(JobId),

    /// Node not found.
    #[error("Node not found: {0}")]
    NodeNotFound(NodeId),

    /// Processor not found.
    #[error("Processor not found: {0}")]
    ProcessorNotFound(ProcessorId),

    /// No suitable processor for operation.
    #[error("No suitable processor for operation: {0}")]
    NoSuitableProcessor(String),

    /// Insufficient resources.
    #[error("Insufficient resources: {0}")]
    InsufficientResources(String),

    /// Task execution failed.
    #[error("Task execution failed: {0}")]
    TaskExecutionFailed(String),

    /// Scheduling failed.
    #[error("Scheduling failed: {0}")]
    SchedulingFailed(String),

    /// Memory allocation failed.
    #[error("Memory allocation failed: {0}")]
    MemoryAllocationFailed(String),

    /// Data transfer failed.
    #[error("Data transfer failed: {0}")]
    DataTransferFailed(String),

    /// Processor type not supported.
    #[error("Processor type not supported: {0:?}")]
    ProcessorTypeNotSupported(ProcessorType),

    /// Operation not supported on processor.
    #[error("Operation not supported on {0:?}: {1}")]
    OperationNotSupported(ProcessorType, String),

    /// Timeout.
    #[error("Operation timed out after {0}ms")]
    Timeout(u64),

    /// Budget exceeded.
    #[error("Budget exceeded: required {required}, available {available}")]
    BudgetExceeded { required: u64, available: u64 },

    /// Node already registered.
    #[error("Node already registered: {0}")]
    NodeAlreadyRegistered(NodeId),

    /// Invalid configuration.
    #[error("Invalid configuration: {0}")]
    InvalidConfiguration(String),

    /// Serialization error.
    #[error("Serialization error: {0}")]
    Serialization(String),

    /// Network error.
    #[error("Network error: {0}")]
    Network(String),

    /// Internal error.
    #[error("Internal error: {0}")]
    Internal(String),

    /// Model not found.
    #[error("Model not found: {0}")]
    ModelNotFound(String),

    /// Model upload failed.
    #[error("Model upload failed: {0}")]
    ModelUploadFailed(String),

    /// Invalid model format.
    #[error("Invalid model format: {0}")]
    InvalidModelFormat(String),
}

impl From<bincode::Error> for ComputeError {
    fn from(err: bincode::Error) -> Self {
        ComputeError::Serialization(err.to_string())
    }
}

impl From<serde_json::Error> for ComputeError {
    fn from(err: serde_json::Error) -> Self {
        ComputeError::Serialization(err.to_string())
    }
}
