use serde_json::json;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum A2aError {
    #[error("Task not found: {0}")]
    TaskNotFound(String),

    #[error("Invalid task state: {current} -> {target}")]
    InvalidStateTransition { current: String, target: String },

    #[error("Coordinator error: {0}")]
    CoordinatorError(String),

    #[error("Unknown skill: {0}")]
    UnknownSkill(String),

    #[error("Serialization error: {0}")]
    SerdeError(#[from] serde_json::error::Error),

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

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

impl A2aError {
    pub fn to_json_rpc_error(&self) -> serde_json::Value {
        let (code, message) = match self {
            A2aError::TaskNotFound(id) => (-32000, format!("Task not found: {}", id)),
            A2aError::InvalidStateTransition { .. } => {
                (-32000, "Invalid state transition".to_string())
            }
            A2aError::UnknownSkill(s) => (-32000, format!("Unknown skill: {}", s)),
            _ => (-32603, "Internal error".to_string()),
        };

        json!({
            "jsonrpc": "2.0",
            "error": {
                "code": code,
                "message": message
            }
        })
    }
}

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