using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;

namespace Mindforge.API.Providers
{
    public class OpenAIApiProvider : ILlmApiProvider
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly IConfiguration _configuration;
        private readonly ILogger<OpenAIApiProvider> _logger;

        public OpenAIApiProvider(IHttpClientFactory httpClientFactory, IConfiguration configuration, ILogger<OpenAIApiProvider> logger)
        {
            _httpClientFactory = httpClientFactory;
            _configuration = configuration;
            _logger = logger;
        }

        public async Task<string> SendRequestAsync(string systemPrompt, string userPrompt)
        {
            var apiUrl = _configuration["OPENAI_API_URL"];
            if (string.IsNullOrEmpty(apiUrl))
                throw new Exception("OPENAI_API_URL not found in configuration.");

            var token = _configuration["OPENAI_TOKEN"];
            if (string.IsNullOrEmpty(token))
                throw new Exception("OPENAI_TOKEN not found in configuration.");

            var model = _configuration["OPENAI_MODEL"];
            if (string.IsNullOrEmpty(model))
                throw new Exception("OPENAI_MODEL not found in configuration.");

            var url = $"{apiUrl.TrimEnd('/')}/chat/completions";

            var reqBody = new
            {
                model = model,
                messages = new[]
                {
                    new { role = "system", content = systemPrompt },
                    new { role = "user", content = userPrompt }
                }
            };

            var jsonBody = JsonSerializer.Serialize(reqBody);

            Exception? lastErr = null;

            using var httpClient = _httpClientFactory.CreateClient();
            httpClient.Timeout = TimeSpan.FromMinutes(5);

            for (int i = 0; i < 5; i++)
            {
                using var request = new HttpRequestMessage(HttpMethod.Post, url);
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
                request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

                try
                {
                    var response = await httpClient.SendAsync(request);
                    var responseBody = await response.Content.ReadAsStringAsync();

                    if (!response.IsSuccessStatusCode)
                    {
                        lastErr = new Exception($"API error status {(int)response.StatusCode}: {responseBody}");
                        await Task.Delay(TimeSpan.FromSeconds(1 << i));
                        continue;
                    }

                    var result = JsonSerializer.Deserialize<JsonElement>(responseBody);
                    if (result.TryGetProperty("choices", out var choices) && choices.GetArrayLength() > 0)
                    {
                        var message = choices[0].GetProperty("message");
                        return message.GetProperty("content").GetString() ?? string.Empty;
                    }

                    _logger.LogWarning("API raw response: {responseBody}", responseBody);
                    throw new Exception("Empty response from API.");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error in API request");
                    lastErr = ex;
                    await Task.Delay(TimeSpan.FromSeconds(1 << i));
                }
            }

            throw new Exception($"Failed to get response after 5 attempts. Last error: {lastErr?.Message}", lastErr);
        }
    }
}
