package com.seer.teach.ai.client.model.openai;

import com.seer.teach.ai.client.model.AbstractAiModelClient;
import com.seer.teach.ai.client.model.config.ModelConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.audio.tts.TextToSpeechModel;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.image.ImageModel;
import org.springframework.ai.model.SimpleApiKey;
import org.springframework.ai.openai.OpenAiAudioSpeechModel;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.OpenAiImageModel;
import org.springframework.ai.openai.OpenAiImageOptions;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.openai.api.OpenAiAudioApi;
import org.springframework.ai.openai.api.OpenAiImageApi;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * OpenAI平台模型管理器
 * 专门负责OpenAI平台的AI模型管理
 *
 * @author Captain
 * @since 2025-12-26
 */
@Slf4j
@Component
public class OpenAIModelClient extends AbstractAiModelClient {

    @Override
    public String getPlatformName() {
        return "openai";
    }

    @Override
    public Optional<ChatModel> createChatModel(ModelConfig modelConfig) {
        OpenAiChatOptions chatOptions = OpenAiChatOptions.builder()
                .model(modelConfig.getModel())
                .build();

        OpenAiApi openAiApi = createOpenAiApi(modelConfig.getApiKey(), modelConfig.getUrl());

        return Optional.of(new OpenAiChatModel(openAiApi, chatOptions, toolCallingManager, retryTemplate, observationRegistry));
    }

    @Override
    public Optional<ChatOptions> createChatOptions(Map<String, Object> options) {
        OpenAiChatOptions.Builder builder = OpenAiChatOptions.builder();
        builder.streamUsage(true);
        for (Map.Entry<String, Object> entry : options.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (Objects.isNull(value)) {
                continue;
            }
            switch (key) {
                case "temperature":
                    builder.temperature(((Number) value).doubleValue());
                    break;
                case "maxTokens":
                    builder.maxTokens(((Number) value).intValue());
                    break;
                case "maxCompletionToken":
                    builder.maxCompletionTokens(((Number) value).intValue());
                    break;
                case "topLogprobs":
                    builder.topLogprobs(((Number) value).intValue());
                    break;
                case "logprobs":
                    builder.logprobs((Boolean) value);
                    break;
                case "N":
                case "n":
                    builder.N(((Number) value).intValue());
                    break;
                case "reasoningEffort":
                    builder.reasoningEffort(value.toString());
                    break;
                case "topP":
                case "top_p":
                    builder.topP(((Number) value).doubleValue());
                    break;
                case "frequencyPenalty":
                    builder.frequencyPenalty(((Number) value).doubleValue());
                    break;
                case "presencePenalty":
                    builder.presencePenalty(((Number) value).doubleValue());
                    break;
                default:
                    break;
            }
        }
        return Optional.of(builder.build());
    }

    @Override
    public Optional<ImageModel> createImageModel(ModelConfig modelConfig) {
        OpenAiImageOptions imageOptions = OpenAiImageOptions.builder()
                .model(modelConfig.getModel())
                .build();

        OpenAiImageApi imageOpenAiApi = OpenAiImageApi.builder()
                .baseUrl(modelConfig.getUrl())
                .apiKey(new SimpleApiKey(modelConfig.getApiKey()))
                .restClientBuilder(restClientBuilder)
                .responseErrorHandler(responseErrorHandler)
                .build();

        return Optional.of(new OpenAiImageModel(imageOpenAiApi, imageOptions, retryTemplate, observationRegistry));
    }

    @Override
    public Optional<TextToSpeechModel> createTextToSpeechModel(ModelConfig modelConfig) {
        try {
            OpenAiAudioApi audioApi = OpenAiAudioApi.builder()
                    .baseUrl(modelConfig.getUrl())
                    .apiKey(new SimpleApiKey(modelConfig.getApiKey()))
                    .restClientBuilder(restClientBuilder)
                    .responseErrorHandler(responseErrorHandler)
                    .build();

            TextToSpeechModel textToSpeechModel = new OpenAiAudioSpeechModel(audioApi);
            return Optional.of(textToSpeechModel);
        } catch (Exception e) {
            log.error("创建OpenAI文本转语音模型失败", e);
            return Optional.empty();
        }
    }

    @Override
    public Optional<EmbeddingModel> createEmbeddingModel(ModelConfig modelConfig) {
        try {
            OpenAiApi openAiApi = createOpenAiApi(modelConfig.getApiKey(), modelConfig.getUrl());
            EmbeddingModel embeddingModel = new OpenAiEmbeddingModel(openAiApi);
            return Optional.of(embeddingModel);
        } catch (Exception e) {
            log.error("创建OpenAI嵌入模型失败", e);
            return Optional.empty();
        }
    }

    private OpenAiApi createOpenAiApi(String apiKey, String baseUrl) {
        return OpenAiApi.builder()
                .baseUrl(baseUrl)
                .apiKey(new SimpleApiKey(apiKey))
                .restClientBuilder(restClientBuilder)
                .webClientBuilder(webClientBuilder).build();
    }
}