using Leanetec.EConnect.Client;
using Leanetec.EConnect.Client.Interface;
using Leanetec.EConnect.Domain.Entities;
using Microsoft.Extensions.Options;
using System.Net.Http.Json;

namespace Leanetec.EConnect.Infrastructure;

public class EConnectClient<TError> : IEConnectClient<TError> where TError :  class
{
    private readonly ClientOptions _options;

    private readonly Lazy<HttpClient> LazyHttp;

    private HttpClient Http => LazyHttp.Value;

    public EConnectClient(IOptions<ClientOptions> options, IHttpClientFactory httpFactory)
    {
        _options = options.Value;
        LazyHttp = new Lazy<HttpClient>(httpFactory.CreateEConnectClient);
    }

    public async Task<Response<TData, TError>> GetAsync<TData>(string? route = null, object? queryParams = null, CancellationToken cancel = default)
        where TData : class
    {
        // add global query strings
        if (_options.QueryStrings is not null)
            route = route.AddQueryString(_options.QueryStrings);

        // add query strings
        if (queryParams is not null)
            route = route.AddQueryString(queryParams.ToPropertyDictionary());

        var res = await Http.GetAsync(route, cancel);

        if (res.IsSuccessStatusCode)
        {
            var data = await res.Content.ReadFromJsonAsync<TData>(cancel);
            return new Response<TData, TError>(true, Data: data);
        }
        else
        {
            var error = await res.Content.ReadFromJsonAsync<TError>(cancel);
            return new Response<TData, TError>(false, Error: error);
        }
    }

    public async Task<Response<IAsyncEnumerable<TData?>, TError>> GetListAsAsyncEnumerable<TData>(string? route = null, object? queryParams = null, CancellationToken cancel = default)
        where TData : class
    {
        // add global query strings
        if (_options.QueryStrings is not null)
            route = route.AddQueryString(_options.QueryStrings);

        // add query strings
        if (queryParams is not null)
            route = route.AddQueryString(queryParams.ToPropertyDictionary());

        var res = await Http.GetAsync(route, cancel);

        if (res.IsSuccessStatusCode)
        {
            var data = res.Content.ReadFromJsonAsAsyncEnumerable<TData>(cancel);
            return new Response<IAsyncEnumerable<TData?>, TError>(true, Data: data);
        }
        else
        {
            var error = await res.Content.ReadFromJsonAsync<TError>(cancellationToken: cancel);
            return new Response<IAsyncEnumerable<TData?>, TError>(false, Error: error);
        }
    }
}
