package rag

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"
)

// chatClient 是 OpenAI 兼容的非流式对话客户端，供图谱实体抽取用。
// 配置由控制面（chat kind）经 NATS 下发（与 Dispatcher 共用同一个模型）。
type chatClient struct {
	baseURL string
	apiKey  string
	model   string
	hc      *http.Client
}

func newChatClient(baseURL, apiKey, model string) *chatClient {
	if baseURL == "" || model == "" {
		return nil
	}
	return &chatClient{baseURL: baseURL, apiKey: apiKey, model: model, hc: &http.Client{Timeout: 60 * time.Second}}
}

func (c *chatClient) ready() bool { return c != nil && c.baseURL != "" }

// complete 一次性补全（非流式），返回助手回复文本。
func (c *chatClient) complete(ctx context.Context, system, user string) (string, error) {
	body, _ := json.Marshal(map[string]any{
		"model": c.model,
		"messages": []map[string]string{
			{"role": "system", "content": system},
			{"role": "user", "content": user},
		},
		"stream": false,
	})
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+"/chat/completions", bytes.NewReader(body))
	if err != nil {
		return "", err
	}
	req.Header.Set("Content-Type", "application/json")
	if c.apiKey != "" {
		req.Header.Set("Authorization", "Bearer "+c.apiKey)
	}
	resp, err := c.hc.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode >= 400 {
		buf := new(bytes.Buffer)
		_, _ = buf.ReadFrom(resp.Body)
		return "", fmt.Errorf("chat http %d: %s", resp.StatusCode, buf.String())
	}
	var out struct {
		Choices []struct {
			Message struct {
				Content string `json:"content"`
			} `json:"message"`
		} `json:"choices"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return "", err
	}
	if len(out.Choices) == 0 {
		return "", fmt.Errorf("chat: empty choices")
	}
	return out.Choices[0].Message.Content, nil
}
