using Microsoft.Extensions.Configuration;
using System.Net.Http.Headers;

namespace Health.Infrastructure.AI;

/// <summary>
/// DeepSeek LLM 客户端（对话 + Tool Calling）
/// </summary>
public sealed class DeepSeekClient(HttpClient http, IConfiguration config)
{
    private readonly HttpClient _http = http;
    private readonly string _model = config["DEEPSEEK_MODEL"] ?? "deepseek-chat";
    private readonly JsonSerializerOptions _jsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
        PropertyNameCaseInsensitive = true
    };

    /// <summary>
    /// 流式 Chat Completions
    /// </summary>
    public async IAsyncEnumerable<string> ChatStreamAsync(
        List<ChatMessage> messages,
        List<ToolDefinition>? tools = null,
        int maxTokens = 2048,
        float temperature = 0.7f,
        [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct = default)
    {
        var request = new ChatCompletionRequest
        {
            Model = _model, Messages = messages, Stream = true,
            MaxTokens = maxTokens, Temperature = temperature, Tools = tools,
        };
        if (tools?.Count > 0) request.ToolChoice = "auto";

        var json = JsonSerializer.Serialize(request, _jsonOptions);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var httpRequest = new HttpRequestMessage(HttpMethod.Post, "chat/completions") { Content = content };
        httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));

        using var response = await _http.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, ct);
        response.EnsureSuccessStatusCode();

        using var stream = await response.Content.ReadAsStreamAsync(ct);
        using var reader = new StreamReader(stream);

        string? line;
        while ((line = await reader.ReadLineAsync(ct)) != null)
        {
            if (string.IsNullOrWhiteSpace(line)) continue;
            if (!line.StartsWith("data: ")) continue;
            var data = line["data: ".Length..];
            if (data == "[DONE]") break;
            yield return data;
        }
    }

    /// <summary>
    /// 非流式 Chat Completions（用于 Tool Calling）
    /// </summary>
    public async Task<ChatCompletionResponse> ChatAsync(
        List<ChatMessage> messages,
        List<ToolDefinition>? tools = null,
        int maxTokens = 2048,
        float temperature = 0.7f,
        CancellationToken ct = default)
    {
        var request = new ChatCompletionRequest
        {
            Model = _model, Messages = messages, Stream = false,
            MaxTokens = maxTokens, Temperature = temperature, Tools = tools,
        };
        if (tools?.Count > 0) request.ToolChoice = "auto";

        var json = JsonSerializer.Serialize(request, _jsonOptions);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await _http.PostAsync("chat/completions", content, ct);
        response.EnsureSuccessStatusCode();

        var body = await response.Content.ReadAsStringAsync(ct);
        return JsonSerializer.Deserialize<ChatCompletionResponse>(body, _jsonOptions)!;
    }
}

/// <summary>
/// VLM 视觉客户端——支持千问/豆包，通过 .env 切换
/// </summary>
public sealed class VisionClient(HttpClient http, IConfiguration config)
{
    private readonly HttpClient _http = http;
    private readonly string _model = config["VLM_MODEL"] ?? "doubao-vision-pro";
    private readonly JsonSerializerOptions _jsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
        PropertyNameCaseInsensitive = true
    };

    public async Task<ChatCompletionResponse> VisionAsync(
        string systemPrompt,
        List<string> imageUrls,
        string? userText = null,
        int maxTokens = 2048,
        CancellationToken ct = default)
    {
        var contentParts = new List<object>();
        foreach (var url in imageUrls)
            contentParts.Add(new { type = "image_url", image_url = new { url } });
        if (!string.IsNullOrEmpty(systemPrompt))
            contentParts.Add(new { type = "text", text = systemPrompt });
        if (!string.IsNullOrEmpty(userText))
            contentParts.Add(new { type = "text", text = userText });

        var messages = new List<ChatMessage>
        {
            new() { Role = "user", Content = contentParts }
        };

        var request = new ChatCompletionRequest
        {
            Model = _model, Messages = messages, MaxTokens = maxTokens, Stream = false,
            Temperature = 0.1f, VlHighResolutionImages = true,
        };

        var json = JsonSerializer.Serialize(request, _jsonOptions);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = await _http.PostAsync("chat/completions", content, ct);
        if (!response.IsSuccessStatusCode)
        {
            var errorBody = await response.Content.ReadAsStringAsync(ct);
            throw new HttpRequestException($"VLM API {response.StatusCode}: {errorBody}");
        }
        var body = await response.Content.ReadAsStringAsync(ct);
        return JsonSerializer.Deserialize<ChatCompletionResponse>(body, _jsonOptions)!;
    }
}
