package com.agent.management.service.impl;

import com.agent.management.common.exception.BusinessException;
import com.agent.management.service.EmbeddingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * EmbeddingService 实现：通过 {@link ObjectProvider} 懒加载 {@link EmbeddingModel}，
 * 当 bean 不存在时（如未配置 api-key 或模型未开通）所有调用都抛业务异常，
 * 但应用本身仍可启动。
 */
@Slf4j
@Service
public class EmbeddingServiceImpl implements EmbeddingService {

    private final ObjectProvider<EmbeddingModel> embeddingModelProvider;

    public EmbeddingServiceImpl(ObjectProvider<EmbeddingModel> embeddingModelProvider) {
        this.embeddingModelProvider = embeddingModelProvider;
    }

    @Override
    public List<float[]> embedBatch(List<String> texts) {
        if (texts == null || texts.isEmpty()) {
            return List.of();
        }
        EmbeddingModel model = embeddingModelProvider.getIfAvailable();
        if (model == null) {
            throw new BusinessException("EmbeddingModel 未装配，请在 application.yml 配置 spring.ai.openai.embedding.options.model 并确保 API 可用");
        }
        try {
            log.info("开始 embedding，文本块数量: {}", texts.size());
            // Spring AI EmbeddingModel 返回 EmbeddingResponse，每个 Embedding 内含 float[]
            var resp = model.embedForResponse(texts);
            List<float[]> result = new ArrayList<>(resp.getResults().size());
            for (var e : resp.getResults()) {
                result.add(e.getOutput());
            }
            log.info("embedding 完成，输出向量数: {}", result.size());
            return result;
        } catch (Exception e) {
            log.error("embedding 调用失败: {}", e.getMessage());
            throw new BusinessException("embedding 调用失败：" + e.getMessage());
        }
    }

    @Override
    public boolean isAvailable() {
        return embeddingModelProvider.getIfAvailable() != null;
    }
}
