namespace TaxBaik.Web.Services.AdminClients;

using System.Collections.Generic;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using TaxBaik.Domain.Entities;
using Microsoft.Extensions.Logging;

public interface ICommonCodeBrowserClient
{
    Task<List<string>> GetGroupsAsync(CancellationToken ct = default);
    Task<List<CommonCode>> GetAllActiveAsync(CancellationToken ct = default);
    Task<List<CommonCode>> GetByGroupAsync(string group, CancellationToken ct = default);
    Task<CommonCode?> GetAsync(string group, string value, CancellationToken ct = default);
    Task<bool> UpsertAsync(CommonCode code, CancellationToken ct = default);
    Task<bool> DeleteAsync(string group, string value, CancellationToken ct = default);
}

public class CommonCodeBrowserClient(HttpClient httpClient, ITokenStore tokenStore, ILogger<CommonCodeBrowserClient> logger) : ICommonCodeBrowserClient
{
    private const string BaseUrl = "/api/commoncode";

    private void EnsureAuthHeader()
    {
        if (!string.IsNullOrEmpty(tokenStore.AccessToken))
            httpClient.DefaultRequestHeaders.Authorization = new("Bearer", tokenStore.AccessToken);
        else
            httpClient.DefaultRequestHeaders.Authorization = null;
    }

    public async Task<List<CommonCode>> GetAllActiveAsync(CancellationToken ct = default)
    {
        try
        {
            EnsureAuthHeader();
            return await httpClient.GetFromJsonAsync<List<CommonCode>>($"{BaseUrl}", ct) ?? [];
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to get all active common codes");
            return [];
        }
    }

    public async Task<List<CommonCode>> GetByGroupAsync(string group, CancellationToken ct = default)
    {
        try
        {
            EnsureAuthHeader();
            return await httpClient.GetFromJsonAsync<List<CommonCode>>($"{BaseUrl}/group/{group}", ct) ?? [];
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to get common codes for group {Group}", group);
            return [];
        }
    }

    public async Task<List<string>> GetGroupsAsync(CancellationToken ct = default)
    {
        try
        {
            EnsureAuthHeader();
            return await httpClient.GetFromJsonAsync<List<string>>($"{BaseUrl}/groups", ct) ?? [];
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to get common code groups");
            return [];
        }
    }

    public async Task<CommonCode?> GetAsync(string group, string value, CancellationToken ct = default)
    {
        try
        {
            EnsureAuthHeader();
            return await httpClient.GetFromJsonAsync<CommonCode>($"{BaseUrl}/{group}/{value}", ct);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to get common code {Group}/{Value}", group, value);
            return null;
        }
    }

    public async Task<bool> UpsertAsync(CommonCode code, CancellationToken ct = default)
    {
        try
        {
            EnsureAuthHeader();
            var response = await httpClient.PostAsJsonAsync(BaseUrl, code, ct);
            return response.IsSuccessStatusCode;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to upsert common code {Group}/{Value}", code.CodeGroup, code.CodeValue);
            return false;
        }
    }

    public async Task<bool> DeleteAsync(string group, string value, CancellationToken ct = default)
    {
        try
        {
            EnsureAuthHeader();
            var response = await httpClient.DeleteAsync($"{BaseUrl}/{group}/{value}", ct);
            return response.IsSuccessStatusCode;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to delete common code {Group}/{Value}", group, value);
            return false;
        }
    }
}
