using Knot.Shared.Kernel;
using Knot.Contracts.Settings.Application.Abstractions;
using Knot.Shared.Kernel.Constants;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using MediatR;

namespace Knot.Modules.Klipy.Application.Klipy.Queries;

public record GetGifCategoriesQuery(string CountryCode = "RU") : IQuery<JsonElement?>;

internal sealed class GetGifCategoriesQueryHandler : IQueryHandler<GetGifCategoriesQuery, JsonElement?>
{
    private readonly IKlipySettings _settings;
    private readonly IMemoryCache _cache;
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IUserContext _userContext;

    public GetGifCategoriesQueryHandler(IKlipySettings settings, IMemoryCache cache, IHttpClientFactory httpClientFactory, IUserContext userContext)
    {
        _settings = settings;
        _cache = cache;
        _httpClientFactory = httpClientFactory;
        _userContext = userContext;
    }

    public async Task<Result<JsonElement?>> Handle(GetGifCategoriesQuery request, CancellationToken cancellationToken)
    {
        var conf = _settings.Current;
        if (!conf.Enabled || string.IsNullOrEmpty(conf.ApiKey))
            return Result.Failure<JsonElement?>(new Error(Errors.KlipyNotConfigured, "Klipy is not configured"));

        var locale = string.IsNullOrEmpty(request.CountryCode) ? "ru_RU" : (request.CountryCode.Length == 2 ? $"{request.CountryCode.ToLowerInvariant()}_{request.CountryCode.ToUpperInvariant()}" : request.CountryCode);
        var customerId = _userContext.IsAuthenticated ? _userContext.UserId.ToString().ToLowerInvariant() : Knot.Shared.Kernel.Constants.Klipy.DefaultCustomerId;

        var cacheKeyCat = $"klipy_categories_{conf.ApiKey}_{locale}";
        if (_cache.TryGetValue(cacheKeyCat, out JsonElement cachedResult))
            return Result.Success<JsonElement?>(cachedResult);

        var client = _httpClientFactory.CreateClient();
        
        // Correct URL according to docs: GET https://api.klipy.com/api/v1/{app_key}/gifs/categories?locale={locale}&customer_id={customer_id}
        var baseUrl = "https://api.klipy.com/api/v1"; 
        var url = $"{baseUrl}/{conf.ApiKey}/gifs/categories?locale={locale}&customer_id={customerId}";

        var response = await client.GetAsync(url, cancellationToken);
        if (!response.IsSuccessStatusCode)
        {
            if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                var urlCo = url.Replace("api.klipy.com", "api.klipy.co");
                response = await client.GetAsync(urlCo, cancellationToken);
            }

            if (!response.IsSuccessStatusCode)
            {
                var errorBody = await response.Content.ReadAsStringAsync(cancellationToken);
                return Result.Failure<JsonElement?>(new Error(Errors.KlipyApiError, $"Klipy Categories API Error: {response.StatusCode} {errorBody}"));
            }
        }

        var result = await response.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: cancellationToken);
        _cache.Set(cacheKeyCat, result, TimeSpan.FromMinutes(Knot.Shared.Kernel.Constants.Klipy.CategoriesCacheMinutes));
        
        return Result.Success<JsonElement?>(result);
    }
}
