package tech.easyflow.ai.service.discovery;

import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.easyflow.ai.entity.Model;
import tech.easyflow.ai.entity.ModelProvider;
import tech.easyflow.ai.mapper.ModelMapper;
import tech.easyflow.ai.mapper.ModelProviderMapper;
import tech.easyflow.ai.service.ModelProviderService;
import tech.easyflow.ai.service.ModelService;
import tech.easyflow.common.web.exceptions.BusinessException;

import java.math.BigInteger;

/**
 * 远端模型一键添加应用服务。
 */
@Service
public class RemoteModelImportService {

    /** 数据库允许的最大模型 ID 长度。 */
    private static final int MAX_MODEL_ID_LENGTH = 255;

    /** 服务商服务。 */
    private final ModelProviderService modelProviderService;
    /** 服务商映射器。 */
    private final ModelProviderMapper modelProviderMapper;
    /** 模型服务。 */
    private final ModelService modelService;
    /** 模型映射器。 */
    private final ModelMapper modelMapper;
    /** 模型元数据解析器。 */
    private final RemoteModelMetadataResolver metadataResolver;

    /**
     * 创建远端模型一键添加服务。
     *
     * @param modelProviderService 服务商服务
     * @param modelProviderMapper 服务商映射器
     * @param modelService 模型服务
     * @param modelMapper 模型映射器
     * @param metadataResolver 模型元数据解析器
     */
    public RemoteModelImportService(ModelProviderService modelProviderService,
                                    ModelProviderMapper modelProviderMapper,
                                    ModelService modelService,
                                    ModelMapper modelMapper,
                                    RemoteModelMetadataResolver metadataResolver) {
        this.modelProviderService = modelProviderService;
        this.modelProviderMapper = modelProviderMapper;
        this.modelService = modelService;
        this.modelMapper = modelMapper;
        this.metadataResolver = metadataResolver;
    }

    /**
     * 幂等添加单个远端模型。
     *
     * @param providerId 服务商 ID
     * @param rawModelId 远端原始模型 ID
     * @param auditModel 已由控制层填充租户和部门字段的模型种子
     * @return 创建或已存在结果
     * @throws BusinessException 参数、服务商或保存结果不合法时抛出
     */
    @Transactional(rollbackFor = Exception.class)
    public RemoteModelImportResult importModel(BigInteger providerId,
                                               String rawModelId,
                                               Model auditModel) {
        if (providerId == null) {
            throw new BusinessException(400, 40031, "服务商 ID 不能为空");
        }
        String modelId = validateModelId(rawModelId);
        ModelProvider provider = modelProviderService.getById(providerId);
        if (provider == null) {
            throw new BusinessException(404, 40431, "模型服务商不存在");
        }

        // 对同一服务商的一键添加串行化，配合唯一键避免并发重复插入。
        if (modelProviderMapper.lockById(providerId) == null) {
            throw new BusinessException(404, 40431, "模型服务商不存在");
        }
        Model existing = findExisting(providerId, modelId);
        if (existing != null) {
            return toResult(existing, RemoteModelImportStatus.ALREADY_EXISTS);
        }

        Model model = auditModel == null ? new Model() : auditModel;
        model.setProviderId(providerId);
        metadataResolver.configureNewModel(model, provider.getProviderType(), modelId);
        modelService.validateForSaveOrUpdate(model, true);
        if (!modelService.save(model)) {
            throw new BusinessException(500, 50031, "添加模型失败，请稍后重试");
        }
        return toResult(model, RemoteModelImportStatus.CREATED);
    }

    /**
     * 校验并规范化模型 ID。
     *
     * @param rawModelId 原始模型 ID
     * @return 去除首尾空白的模型 ID
     */
    private String validateModelId(String rawModelId) {
        if (rawModelId == null || rawModelId.trim().isEmpty()) {
            throw new BusinessException(400, 40032, "模型 ID 不能为空");
        }
        String modelId = rawModelId.trim();
        if (modelId.codePointCount(0, modelId.length()) > MAX_MODEL_ID_LENGTH) {
            throw new BusinessException(422, 42232, "模型 ID 不能超过 255 个字符");
        }
        if (modelId.chars().anyMatch(Character::isISOControl)) {
            throw new BusinessException(422, 42233, "模型 ID 包含非法控制字符");
        }
        return modelId;
    }

    /**
     * 查询当前租户下已存在的相同模型。
     *
     * @param providerId 服务商 ID
     * @param modelId 原始模型 ID
     * @return 已存在模型，不存在时返回 null
     */
    private Model findExisting(BigInteger providerId, String modelId) {
        QueryWrapper query = QueryWrapper.create()
                .eq(Model::getProviderId, providerId)
                .eq(Model::getModelName, modelId);
        return modelMapper.selectOneByQuery(query);
    }

    /**
     * 构建添加接口结果。
     *
     * @param model 本地模型
     * @param status 添加状态
     * @return 添加接口结果
     */
    private RemoteModelImportResult toResult(Model model, RemoteModelImportStatus status) {
        return new RemoteModelImportResult(
                model.getModelName(), model.getId(), model.getModelType(), status);
    }
}
