using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using UniVerse.Application.Interfaces;
using UniVerse.Application.Prompts;

namespace UniVerse.Infrastructure.ExternalServices;

public class LlmClient : ILlmClient
{
    private readonly HttpClient _http;
    private readonly IConfiguration _config;
    private readonly IReviewPromptService _reviewPrompts;
    private readonly ILogger<LlmClient> _logger;

    public LlmClient(
        HttpClient http,
        IConfiguration config,
        IReviewPromptService reviewPrompts,
        ILogger<LlmClient> logger)
    {
        _http = http;
        _config = config;
        _reviewPrompts = reviewPrompts;
        _logger = logger;
    }

    public async Task<LlmReviewAnalysis> AnalyzeReviewAsync(string reviewText, string lectureContext)
    {
        var promptSetting = await _reviewPrompts.GetAsync();
        var prompt = ReviewPromptTemplate.Render(promptSetting.Prompt, reviewText, lectureContext);

        var request = new
        {
            model = _config["Llm:Model"] ?? "gpt-4o-mini",
            messages = new[] { new { role = "user", content = prompt } },
            temperature = 0.3,
            response_format = new { type = "json_object" }
        };

        var apiKey = _config["Llm:ApiKey"] ?? "";
        _http.DefaultRequestHeaders.Clear();
        if (!string.IsNullOrEmpty(apiKey))
            _http.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");

        var response = await _http.PostAsJsonAsync("chat/completions", request);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadFromJsonAsync<JsonElement>();
        var content = json.GetProperty("choices")[0].GetProperty("message").GetProperty("content").GetString()!;
        var analysisJson = NormalizeJsonContent(content);
        var analysis = JsonSerializer.Deserialize<LlmRawResponse>(analysisJson,
            new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!;

        return new LlmReviewAnalysis(
            Math.Clamp(analysis.QualityScore, 0, 1),
            analysis.Sentiment ?? "",
            analysis.Tags ?? [],
            analysis.IsInformative,
            content);
    }

    private static string NormalizeJsonContent(string content)
    {
        var trimmed = content.Trim();
        if (!trimmed.StartsWith("```", StringComparison.Ordinal))
            return trimmed;

        var firstNewLine = trimmed.IndexOf('\n');
        if (firstNewLine < 0)
            return trimmed;

        var lastFence = trimmed.LastIndexOf("```", StringComparison.Ordinal);
        return lastFence > firstNewLine
            ? trimmed[(firstNewLine + 1)..lastFence].Trim()
            : trimmed[(firstNewLine + 1)..].Trim();
    }

    private record LlmRawResponse(
        [property: JsonPropertyName("quality_score")] double QualityScore,
        string? Sentiment,
        string[]? Tags,
        [property: JsonPropertyName("is_informative")] bool IsInformative);
}
