using JsonRpcEndpointSample.Rpc.Abstractions;
using Microsoft.Extensions.DependencyInjection;

namespace JsonRpcEndpointSample.Rpc;

public sealed class JsonRpcDispatcher : IJsonRpcDispatcher
{
    private readonly IServiceProvider _serviceProvider;

    public JsonRpcDispatcher(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public async Task<JsonRpcResponse> DispatchAsync(JsonRpcRequest request)
    {
        if (request.JsonRpc != "2.0")
        {
            return JsonRpcResponse.CreateError(request.Id, -32600, "Invalid Request");
        }

        if (string.IsNullOrWhiteSpace(request.Method))
        {
            return JsonRpcResponse.CreateError(request.Id, -32600, "Invalid Request");
        }

        IRpcRequestHandler? handler = _serviceProvider.GetKeyedService<IRpcRequestHandler>(request.Method);

        if (handler == null)
        {
            return JsonRpcResponse.CreateError(request.Id, -32601, "Method not found");
        }

        try
        {
            object? result = await handler.HandleAsync(request.Params);
            return JsonRpcResponse.CreateResult(request.Id, result);
        }
        catch (Exception exception)
        {
            return JsonRpcResponse.CreateError(request.Id, -32603, exception.Message);
        }
    }
}
