// PRE-GENERATED (design session). OpenAI (ChatGPT) provider via function calling. Untested.
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;

namespace DansoriEQ.Core.Ai;

public sealed class OpenAiProvider : IAiEqProvider
{
    private const string Endpoint = "https://api.openai.com/v1/chat/completions";
    private readonly HttpClient _http;
    private readonly string _key;
    private readonly string _model;

    public OpenAiProvider(string apiKey, string? model = null, HttpClient? http = null)
    {
        _key = apiKey;
        _model = string.IsNullOrWhiteSpace(model) ? "gpt-4o-mini" : model!;
        _http = http ?? new HttpClient();
    }

    public async Task<EqDelta> RequestEqAsync(string headphoneName, string type, string currentEqText,
                                              string userRequest, CancellationToken ct = default)
    {
        var schema = JsonNode.Parse(EqPromptBuilder.ToolInputSchemaJson)!;
        var body = new JsonObject
        {
            ["model"] = _model,
            ["messages"] = new JsonArray(
                new JsonObject { ["role"] = "system", ["content"] = EqPromptBuilder.SystemPrompt },
                new JsonObject { ["role"] = "user", ["content"] = EqPromptBuilder.BuildUserContext(headphoneName, type, currentEqText, userRequest) }),
            ["tools"] = new JsonArray(new JsonObject
            {
                ["type"] = "function",
                ["function"] = new JsonObject
                {
                    ["name"] = EqPromptBuilder.ToolName,
                    ["description"] = "Set the parametric equalizer bands and preamp.",
                    ["parameters"] = schema
                }
            }),
            ["tool_choice"] = new JsonObject
            {
                ["type"] = "function",
                ["function"] = new JsonObject { ["name"] = EqPromptBuilder.ToolName }
            }
        };

        using var req = new HttpRequestMessage(HttpMethod.Post, Endpoint);
        req.Headers.Add("Authorization", "Bearer " + _key);
        req.Content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");

        using var resp = await _http.SendAsync(req, ct);
        var json = await resp.Content.ReadAsStringAsync(ct);
        if (!resp.IsSuccessStatusCode)
            throw new InvalidOperationException($"OpenAI 요청 실패 ({(int)resp.StatusCode}): {json}");

        using var doc = JsonDocument.Parse(json);
        var args = doc.RootElement.GetProperty("choices")[0].GetProperty("message")
                      .GetProperty("tool_calls")[0].GetProperty("function")
                      .GetProperty("arguments").GetString() ?? "{}";
        return EqDeltaParser.FromJsonText(args);
    }
}
