using System.Text.Json;
using Microsoft.JSInterop;
using RpgRoller.Contracts;

namespace RpgRoller.Components;

public sealed class RpgRollerApiClient(IJSRuntime js)
{
    private sealed class JsApiResponse
    {
        public bool Ok { get; set; }
        public int Status { get; set; }
        public string? Error { get; set; }
        public string? Code { get; set; }
        public JsonElement Data { get; set; }
    }

    public async Task<T> RequestAsync<T>(string method, string path, object? payload = null)
    {
        var response = await js.InvokeAsync<JsApiResponse>("rpgRollerApi.request", method, path, payload);
        if (!response.Ok)
            throw new ApiRequestException(response.Status, response.Error ?? "Request failed.", response.Code);

        if (response.Data.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null)
            return default!;

        return response.Data.Deserialize<T>(JsonOptions)!;
    }

    public async Task RequestWithoutPayloadAsync(string method, string path)
    {
        var response = await js.InvokeAsync<JsApiResponse>("rpgRollerApi.request", method, path, null);
        if (!response.Ok)
            throw new ApiRequestException(response.Status, response.Error ?? "Request failed.", response.Code);
    }

    private static readonly JsonSerializerOptions JsonOptions = RpgRollerJson.CreateSerializerOptions();
}

public sealed class ApiRequestException(int statusCode, string message, string? errorCode = null) : Exception(message)
{
    public int StatusCode { get; } = statusCode;
    public string? ErrorCode { get; } = errorCode;
}