package cn.com.poc.agent_application.service.impl;

import cn.com.poc.agent_application.constant.AgentApplicationConstants;
import cn.com.poc.agent_application.entity.Variable;
import cn.com.poc.agent_application.query.AgentApplicationInfoQueryCondition;
import cn.com.poc.agent_application.query.AgentApplicationInfoQueryItem;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.UUIDTool;
import cn.com.yict.framemax.core.i18n.I18nMessageException;
import cn.com.yict.framemax.core.service.impl.BaseServiceImpl;
import cn.com.poc.agent_application.service.BizAgentApplicationInfoService;
import cn.com.poc.agent_application.model.BizAgentApplicationInfoModel;
import cn.com.poc.agent_application.entity.BizAgentApplicationInfoEntity;
import cn.com.poc.agent_application.convert.AgentApplicationInfoConvert;
import cn.com.poc.agent_application.repository.BizAgentApplicationInfoRepository;
import cn.com.yict.framemax.data.model.PagingInfo;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.List;
import javax.annotation.Resource;

import org.springframework.util.Assert;

@Service
public class BizAgentApplicationInfoServiceImpl extends BaseServiceImpl
        implements BizAgentApplicationInfoService {

    @Resource
    private BizAgentApplicationInfoRepository repository;

    @Override
    public BizAgentApplicationInfoEntity getByAgentId(String agentId) {
        Assert.notNull(agentId);
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        model.setAgentId(agentId);
        model.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model);
        if (CollectionUtils.isEmpty(models)) {
            return null;
        }
        return AgentApplicationInfoConvert.modelToEntity(models.get(0));
    }

    @Override
    public void deletedByAgentId(String agentId) {
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        model.setAgentId(agentId);
        model.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model);
        if (CollectionUtils.isNotEmpty(models)) {
            BizAgentApplicationInfoModel bizAgentApplicationInfoModel = models.get(0);
            bizAgentApplicationInfoModel.setIsDeleted(CommonConstant.IsDeleted.Y);
            this.repository.save(bizAgentApplicationInfoModel);
        }
    }

    @Override
    public List<BizAgentApplicationInfoEntity> findByExample(BizAgentApplicationInfoEntity example, PagingInfo pagingInfo) {
        List<BizAgentApplicationInfoEntity> result = new ArrayList<BizAgentApplicationInfoEntity>();
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        if (example != null) {
            model = AgentApplicationInfoConvert.entityToModel(example);
        }
        model.setIsDeleted("N");
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model, "created_time desc", pagingInfo);
        if (CollectionUtils.isNotEmpty(models)) {
            result = models.stream().map(AgentApplicationInfoConvert::modelToEntity).collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public List<BizAgentApplicationInfoEntity> agentApplicationInfoQuery(AgentApplicationInfoQueryCondition condition, PagingInfo pagingInfo) {
        List<BizAgentApplicationInfoEntity> result = new ArrayList<>();
        List<AgentApplicationInfoQueryItem> items = this.sqlDao.query(condition, AgentApplicationInfoQueryItem.class, pagingInfo);
        if (CollectionUtils.isNotEmpty(items)) {
            result = items.stream().map(AgentApplicationInfoConvert::queryItemToEntity).collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public BizAgentApplicationInfoEntity save(BizAgentApplicationInfoEntity entity) throws Exception {
        Assert.notNull(entity);
        entity.setId(null);
        entity.setIsDeleted("N");
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        paramVerificationAndConvert(entity, model);
        model.setAgentId(UUIDTool.getUUID());
        BizAgentApplicationInfoModel saveModel = this.repository.save(model);
        return AgentApplicationInfoConvert.modelToEntity(saveModel);
    }

    @Override
    public BizAgentApplicationInfoEntity update(BizAgentApplicationInfoEntity entity) throws Exception {
        Assert.notNull(entity);
        Assert.notNull(entity.getAgentId(), "agent id can not be null");
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        model.setAgentId(entity.getAgentId());
        model.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model);
        if (CollectionUtils.isEmpty(models)) {
            throw new I18nMessageException("exception/data.does.not.exist");
        }
        model = models.get(0);
        paramVerificationAndConvert(entity, model);
        BizAgentApplicationInfoModel saveModel = this.repository.save(model);
        return AgentApplicationInfoConvert.modelToEntity(saveModel);
    }

    @Override
    public BizAgentApplicationInfoEntity saveOrUpdate(BizAgentApplicationInfoEntity entity) throws Exception {
        Assert.notNull(entity);
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        BeanUtils.copyProperties(entity, model);
        if (StringUtils.isBlank(entity.getAgentId())) {
            model.setAgentId(UUIDTool.getUUID());
        }
        BizAgentApplicationInfoModel saveModel = this.repository.save(model);
        return AgentApplicationInfoConvert.modelToEntity(saveModel);
    }

    @Override
    public boolean publish(String agentId) {
        Assert.notNull(agentId);
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        model.setAgentId(agentId);
        model.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model);
        if (CollectionUtils.isEmpty(models)) {
            return false;
        }
        model = models.get(0);
        model.setAgentPublishStatus(AgentApplicationConstants.AGENT_PUBLISH_STATUS.PUBLISH);
        this.repository.save(model);
        return true;
    }

    @Override
    public boolean unPublish(String agentId) {
        Assert.notNull(agentId);
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        model.setAgentId(agentId);
        model.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model);
        if (CollectionUtils.isEmpty(models)) {
            return false;
        }
        model = models.get(0);
        model.setAgentPublishStatus(AgentApplicationConstants.AGENT_PUBLISH_STATUS.UN_PUBLISH);
        this.repository.save(model);
        return true;
    }

    @Override
    public BizAgentApplicationInfoEntity saveVariableStructure(String agentId, List<Variable> variableStructure) {
        Assert.notNull(agentId);
        BizAgentApplicationInfoModel model = new BizAgentApplicationInfoModel();
        model.setAgentId(agentId);
        model.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationInfoModel> models = this.repository.findByExample(model);
        if (CollectionUtils.isEmpty(models)) {
            return null;
        }
        BizAgentApplicationInfoModel updateModel = models.get(0);
        String variableStructureStr = null;
        if (CollectionUtils.isNotEmpty(variableStructure)) {
            variableStructureStr = JsonUtils.serialize(variableStructure);
        }
        updateModel.setVariableStructure(variableStructureStr);
        BizAgentApplicationInfoModel saveModel = this.repository.save(updateModel);
        return AgentApplicationInfoConvert.modelToEntity(saveModel);
    }

    /**
     * 参数验证和转换 Entity To Model
     *
     * @param entity
     * @param model
     */
    private void paramVerificationAndConvert(BizAgentApplicationInfoEntity entity, BizAgentApplicationInfoModel model) {
        model.setMemberId(entity.getMemberId());
        model.setAgentTitle(entity.getAgentTitle());
        model.setAgentDesc(entity.getAgentDesc());
        model.setAgentSystem(entity.getAgentSystem());
        model.setAgentAvatar(entity.getAgentAvatar());
        if (StringUtils.isNotBlank(entity.getAgentPublishStatus())) {
            Assert.isTrue(AgentApplicationConstants.AGENT_PUBLISH_STATUS.isPublishStatus(entity.getAgentPublishStatus()), "Agent publish status is error");
        }
        model.setAgentPublishStatus(entity.getAgentPublishStatus());
        model.setPreamble(entity.getPreamble());
        model.setFeaturedQuestions(JsonUtils.serialize(entity.getFeaturedQuestions()));
        if (entity.getCommunicationTurn() != null) {
            Assert.isTrue(entity.getCommunicationTurn() >= 0 && entity.getCommunicationTurn() <= 100, "communication turn is error,must more than 0 and less than 100");
        }
        model.setCommunicationTurn(entity.getCommunicationTurn());
        if (StringUtils.isNotBlank(entity.getContinuousQuestionStatus())) {
            Assert.isTrue(AgentApplicationConstants.CONTINUOUS_QUESTION_STATUS.isQuestionStatus(entity.getContinuousQuestionStatus())
                    , "continuous question status is error , must in default , customizable and close.");
        }
        if (entity.getTopP() != null) {
            Assert.isTrue(entity.getTopP() >= 0 && entity.getTopP() <= 1.00, "top p is error,must more than 0 and less than 1.0");
        }
        if (entity.getTemperature() != null) {
            Assert.isTrue(entity.getTemperature() > 0 && entity.getTemperature() <= 1.0, "temperature is error,must greater than 0, less than or equal to 1.9");
        }
        if (entity.getVoiceConfig() != null) {
            model.setVoiceConfig(JsonUtils.serialize(entity.getVoiceConfig()));
        }
        if (StringUtils.isNotBlank(entity.getIsDocumentParsing())) {
            model.setIsDocumentParsing(entity.getIsDocumentParsing());
        }
        if (StringUtils.isNotBlank(entity.getIsLongMemory())) {
            model.setIsLongMemory(entity.getIsLongMemory());
        }
        model.setTemperature(entity.getTemperature());
        model.setTopP(entity.getTopP());
        model.setContinuousQuestionStatus(entity.getContinuousQuestionStatus());
        model.setContinuousQuestionSystem(entity.getContinuousQuestionSystem());
        model.setKnowledgeIds(JsonUtils.serialize(entity.getKnowledgeIds()));
        if (StringUtils.isNotBlank(entity.getKnowledgeSearchType())) {
            model.setKnowledgeSearchType(entity.getKnowledgeSearchType());
        }
        if (entity.getKnowledgeSimilarity() != null) {
            model.setKnowledgeSimilarity(entity.getKnowledgeSimilarity());
        }
        if (entity.getKnowledgeNResult() != null) {
            model.setKnowledgeNResult(entity.getKnowledgeNResult());
        }
        model.setKnowledgeResponseType(entity.getKnowledgeResponseType());
        if (ArrayUtils.isNotEmpty(entity.getKnowledgeCustomResponse())) {
            model.setKnowledgeCustomResponse(ArrayUtils.isNotEmpty(entity.getKnowledgeCustomResponse()) ? JsonUtils.serialize(entity.getKnowledgeCustomResponse()) : null);
        }
        model.setVariableStructure(JsonUtils.serialize(entity.getVariableStructure()));
        model.setLargeModel(entity.getLargeModel());
        model.setUnitIds(JsonUtils.serialize(entity.getUnitIds()));
    }
}