using System.Diagnostics;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

namespace Nalu.Web.Services.LlmRouter;

public class OpenRouterProvider(HttpClient http, IConfiguration config, ILogger<OpenRouterProvider> logger) : ILlmProvider
{
    public string Name => "openrouter";

    public async Task<LlmResponse> CompleteAsync(LlmRequest request, CancellationToken ct)
    {
        var model = config["OpenRouter:Model"] ?? "meta-llama/llama-3.3-70b-instruct";
        var body = new
        {
            model,
            messages = new[]
            {
                new { role = "system", content = request.SystemPrompt },
                new { role = "user",   content = request.UserMessage }
            },
            max_tokens = request.MaxTokens,
            temperature = request.Temperature,
            response_format = new { type = "json_object" }
        };

        var sw = Stopwatch.StartNew();
        using var httpReq = new HttpRequestMessage(HttpMethod.Post, "chat/completions")
        {
            Content = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json")
        };

        HttpResponseMessage resp;
        try
        {
            resp = await http.SendAsync(httpReq, ct);
        }
        catch (TaskCanceledException) when (!ct.IsCancellationRequested)
        {
            throw new TimeoutException("OpenRouter request timed out");
        }

        if (resp.StatusCode == HttpStatusCode.TooManyRequests)
            throw new RateLimitException(Name);

        if ((int)resp.StatusCode >= 500)
        {
            logger.LogWarning("OpenRouter server error {Status}", resp.StatusCode);
            throw new RateLimitException(Name);
        }

        if (!resp.IsSuccessStatusCode)
        {
            var err = await resp.Content.ReadAsStringAsync(ct);
            throw new InvalidOperationException($"OpenRouter {resp.StatusCode}: {err}");
        }

        var json = await resp.Content.ReadAsStringAsync(ct);
        var doc = JsonNode.Parse(json);
        var content = doc?["choices"]?[0]?["message"]?["content"]?.GetValue<string>();

        return new LlmResponse
        {
            Content = content ?? throw new InvalidOperationException("Empty content in OpenRouter response"),
            Provider = Name,
            LatencyMs = (int)sw.ElapsedMilliseconds
        };
    }
}
