//! Error types for the makima daemon.

use thiserror::Error;
use uuid::Uuid;

/// Top-level daemon error type.
#[derive(Error, Debug)]
pub enum DaemonError {
    #[error("WebSocket error: {0}")]
    WebSocket(#[from] tokio_tungstenite::tungstenite::Error),

    #[error("Worktree error: {0}")]
    Worktree(#[from] crate::daemon::worktree::WorktreeError),

    #[error("Process error: {0}")]
    Process(#[from] crate::daemon::process::ClaudeProcessError),

    #[error("Task error: {0}")]
    Task(#[from] TaskError),

    #[error("Configuration error: {0}")]
    Config(#[from] config::ConfigError),

    #[error("Database error: {0}")]
    Database(#[from] rusqlite::Error),

    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    #[error("JSON error: {0}")]
    Json(#[from] serde_json::Error),

    #[error("Storage error: {0}")]
    Storage(#[from] crate::daemon::storage::PatchError),

    #[error("Authentication failed: {0}")]
    AuthFailed(String),

    #[error("Connection lost")]
    ConnectionLost,

    #[error("Server error: {code} - {message}")]
    ServerError { code: String, message: String },
}

/// Task management errors.
#[derive(Error, Debug)]
pub enum TaskError {
    #[error("Task not found: {0}")]
    NotFound(Uuid),

    #[error("Invalid state transition from {from} to {to}")]
    InvalidStateTransition { from: String, to: String },

    #[error("Global concurrency limit reached")]
    ConcurrencyLimit,

    #[error("Contract concurrency limit reached")]
    ContractConcurrencyLimit,

    #[error("Task already exists: {0}")]
    AlreadyExists(Uuid),

    #[error("Task not running: {0}")]
    NotRunning(Uuid),

    #[error("Failed to send message to task: {0}")]
    MessageFailed(String),

    #[error("Task setup failed: {0}")]
    SetupFailed(String),

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

/// Result type alias for daemon operations.
pub type Result<T> = std::result::Result<T, DaemonError>;

/// Result type alias for task operations.
pub type TaskResult<T> = std::result::Result<T, TaskError>;
