package com.infoepoch.pms.agent.platform.model.adapter.out.ai;

import com.infoepoch.pms.agent.platform.model.domain.AiModelConfig;
import com.infoepoch.pms.agent.platform.model.domain.irepository.ISystemSettingsRepository;
import com.infoepoch.pms.agent.platform.model.application.ModelQueryService;
import com.infoepoch.pms.agent.platform.model.domain.SystemSettings;
import com.infoepoch.pms.agent.platform.shared.exception.BusinessException;
import com.infoepoch.pms.agent.platform.shared.response.ResultCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ChatModel 工厂。
 * <p>
 * {@code create(config)} - 根据指定的 {@link AiModelConfig} 构建或从缓存中返回 ChatModel。<br>
 * {@code create(null)} - 从 {@code system_settings.default_model_config_id} 读取全局默认模型配置后构建。
 * 若未配置则抛出 {@link BusinessException}（{@code DEFAULT_MODEL_NOT_SET}）。
 * </p>
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ChatModelFactory {

    /** 系统设置里保存默认模型配置 ID 的键名。 */
    /**
     * 默认模型配置 ID 在 system_settings 中对应的键。
     */
    static final String DEFAULT_MODEL_KEY = "default_model_config_id";

    private final ISystemSettingsRepository systemSettingsRepository;
    private final ModelQueryService modelQueryService;
    private final List<ProviderChatModelBuilder> builders;
    private final Map<String, ChatModel> modelCache = new ConcurrentHashMap<>();

    /**
     * 构建或返回缓存的 ChatModel。
     * <p>
     * 缓存键为模型配置 ID；当模型配置或其供应商发生变更时，由 Service 层显式触发失效。
     * </p>
     *
     * @param config 模型配置，传 {@code null} 时使用全局默认模型
     * @return 已构建的 ChatModel
     * @throws BusinessException DEFAULT_MODEL_NOT_SET 若全局默认模型未配置
     * @throws BusinessException MODEL_CONFIG_NOT_FOUND 若默认模型指向的配置不存在
     * @throws BusinessException PARAM_ERROR 若供应商类型无对应 Builder
     */
    public ChatModel create(AiModelConfig config) {
        if (config == null) {
            return createDefault();
        }
        return buildWithCache(config);
    }

    /**
     * 创建全局默认模型对应的 ChatModel。
     *
     * @return ChatModel
     */
    private ChatModel createDefault() {
        SystemSettings settings = systemSettingsRepository.findById(DEFAULT_MODEL_KEY)
                .orElseThrow(() -> new BusinessException(ResultCode.DEFAULT_MODEL_NOT_SET,
                        "未设置全局默认模型，请前往系统设置配置"));

        String value = settings.getValue();
        if (!StringUtils.hasText(value)) {
            throw new BusinessException(ResultCode.DEFAULT_MODEL_NOT_SET,
                    "未设置全局默认模型，请前往系统设置配置");
        }

        String configId = value.trim();
        AiModelConfig defaultConfig = modelQueryService.getModelConfigOrNull(configId);

        return buildWithCache(defaultConfig);
    }

    /**
     * 构建或复用缓存中的 ChatModel。
     *
     * @param config 模型配置
     * @return ChatModel
     */
    private ChatModel buildWithCache(AiModelConfig config) {
        String configId = config.getId();
        if (configId == null) {
            return buildChatModel(config);
        }
        try {
            return modelCache.computeIfAbsent(configId, key -> buildChatModel(config));
        } catch (BusinessException ex) {
            modelCache.remove(configId);
            throw ex;
        } catch (RuntimeException ex) {
            modelCache.remove(configId);
            if (ex.getCause() instanceof BusinessException businessException) {
                throw businessException;
            }
            throw new BusinessException(ResultCode.SYSTEM_ERROR, "构建 ChatModel 失败");
        }
    }

    private ChatModel buildChatModel(AiModelConfig config) {
        String providerType = config.getProvider().getType();
        log.info("Building new ChatModel for provider type: {}, model: {}", providerType, config.getModelName());
        for (ProviderChatModelBuilder builder : builders) {
            if (builder.supports(providerType)) {
                return builder.build(config);
            }
        }
        throw new BusinessException(ResultCode.PARAM_ERROR, "不支持的模型供应商类型: " + providerType);
    }

    /**
     * 失效指定模型配置对应的缓存。
     *
     * @param configId 模型配置 ID
     */
    public void evict(String configId) {
        if (configId != null) {
            modelCache.remove(configId);
        }
    }

    /**
     * 清空全部模型缓存。
     */
    public void clear() {
        modelCache.clear();
    }
}
