// Package assistant 实现管理平台 AI 助手:基于实时平台统计信息(供应商、
// 模型、账号、用量、事件投递等)回答管理员的自然语言问题。
package assistant

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"time"

	"aigateway.local/core/internal/gateway"
	"github.com/jackc/pgx/v5/pgxpool"
)

var ErrUnavailable = errors.New("AI 助手服务暂不可用")

// Resolver 提供默认模型供应商(注入 gateway 的 provider resolver)。
type Resolver interface {
	Resolve(code string) (gateway.ResolvedAdapter, error)
}

// Service 管理平台 AI 助手。
type Service struct {
	pool     *pgxpool.Pool
	resolver Resolver
	client   *http.Client
	logger   *slog.Logger
	model    string
}

func NewService(pool *pgxpool.Pool, resolver Resolver, model string, logger *slog.Logger) *Service {
	return &Service{
		pool: pool, resolver: resolver, logger: logger, model: model,
		client: &http.Client{Timeout: 60 * time.Second},
	}
}

// Answer 回答管理员提问。
func (s *Service) Answer(ctx context.Context, message string) (string, error) {
	if s == nil || s.resolver == nil {
		return "", ErrUnavailable
	}
	resolved, err := s.resolver.Resolve("")
	if err != nil {
		return "", fmt.Errorf("%w: 未配置默认模型供应商", ErrUnavailable)
	}
	model := s.model
	if model == "" {
		model = "gpt-4o-mini" // 兜底;实际以上游支持为准
	}
	systemPrompt, err := s.platformSummary(ctx)
	if err != nil {
		s.logger.Warn("assistant platform summary failed", "error", err)
		systemPrompt = "你是 AI 网关管理助手的系统提示,请基于平台知识回答。"
	}
	payload, _ := json.Marshal(map[string]any{
		"model": model,
		"messages": []map[string]any{
			{"role": "system", "content": systemPrompt},
			{"role": "user", "content": message},
		},
		"temperature": 0.2,
	})
	request, err := http.NewRequestWithContext(ctx, http.MethodPost, resolved.Adapter.Target().String()+"/v1/chat/completions", bytes.NewReader(payload))
	if err != nil {
		return "", err
	}
	request.Header.Set("Content-Type", "application/json")
	resolved.Adapter.Prepare(request)
	response, err := s.client.Do(request)
	if err != nil {
		return "", fmt.Errorf("%w: 模型调用失败: %v", ErrUnavailable, err)
	}
	defer response.Body.Close()
	raw, _ := io.ReadAll(io.LimitReader(response.Body, 1<<20))
	if response.StatusCode/100 != 2 {
		return "", fmt.Errorf("%w: 模型返回 HTTP %d", ErrUnavailable, response.StatusCode)
	}
	var decoded struct {
		Choices []struct {
			Message struct {
				Content string `json:"content"`
			} `json:"message"`
		} `json:"choices"`
	}
	if json.Unmarshal(raw, &decoded) != nil || len(decoded.Choices) == 0 {
		return "", fmt.Errorf("%w: 模型响应格式无效", ErrUnavailable)
	}
	return decoded.Choices[0].Message.Content, nil
}

// platformSummary 汇总平台实时状态注入系统提示。
func (s *Service) platformSummary(ctx context.Context) (string, error) {
	var providers, models, admins, portals, apiKeys, pendingOutbox, todayRequests, todayTokens int64
	_ = s.pool.QueryRow(ctx, `SELECT (SELECT count(*) FROM gateway.providers WHERE enabled), (SELECT count(*) FROM gateway.provider_models WHERE enabled), (SELECT count(*) FROM gateway.admin_accounts), (SELECT count(*) FROM gateway.portal_users), (SELECT count(*) FROM gateway.api_keys WHERE enabled), (SELECT count(*) FROM gateway.outbox_events WHERE status='pending'), (SELECT count(*) FROM gateway.audit_events WHERE recorded_at >= date_trunc('day', now())), (SELECT COALESCE(sum(prompt_tokens+completion_tokens),0) FROM gateway.audit_events WHERE recorded_at >= date_trunc('day', now()))`).Scan(&providers, &models, &admins, &portals, &apiKeys, &pendingOutbox, &todayRequests, &todayTokens)
	return fmt.Sprintf(`你是 AI 网关管理助手。以下是平台实时状态(由系统注入,回答时请引用准确数字):
- 启用模型供应商: %d 个
- 启用的上游模型: %d 个
- 管理员账号: %d 个, 门户账号: %d 个
- 启用 API Key: %d 个
- 待处理 outbox 事件: %d 条
- 今日请求: %d 次, 今日 Token 消耗: %d
请用中文简洁回答管理员的问题;涉及平台配置建议时说明操作路径(如"供应商管理→新增供应商")。`, providers, models, admins, portals, apiKeys, pendingOutbox, todayRequests, todayTokens), nil
}
