package com.huigou.rule.application.impl;

import com.huigou.data.domain.model.CommonDomainConstants;
import com.huigou.data.domain.service.CommonDomainService;
import com.huigou.rule.application.RuleApplication;
import com.huigou.rule.domain.model.Rule;
import com.huigou.rule.domain.query.RuleQueryRequest;
import com.huigou.rule.mapper.RuleMapper;
import com.huigou.rule.repository.RuleRepository;
import com.huigou.uasp.bpm.FlowBroker;
import org.activiti.engine.RepositoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.ByteArrayInputStream;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class RuleApplicationImpl extends FlowBroker implements RuleApplication {

    @Autowired
    private RuleMapper ruleMapper;
    @Autowired
    private RuleRepository ruleRepository;
    @Autowired
    private CommonDomainService commonDomainService;
    @Autowired
    private RepositoryService repositoryService;

    @Override
    public void saveRule(Rule rule) {
        checkCodeConstraints(rule);
        commonDomainService.saveBaseInfoWithFolderEntity(rule, ruleRepository);
    }

    @Override
    public Map<String, Object> slicedQueryRules(RuleQueryRequest request) {
        return ruleMapper.slicedQueryRules(request);
    }

    @Override
    public void updateRuleStatus(List<String> ids, Integer status) {
        checkIdsNotEmpty(ids);
        Assert.notNull(status, String.format(CommonDomainConstants.PARAMETER_NOT_NULL_FORMAT, CommonDomainConstants.STATUS_FIELD_NAME));
        commonDomainService.updateStatus(Rule.class, ids, status);
    }

    @Override
    public void moveRules(List<String> ids, String folderId) {
        this.checkIdsNotEmpty(ids);
        this.checkFolderIdNotBlank(folderId);
        this.commonDomainService.moveForFolder(Rule.class, ids, folderId);
    }

    @Override
    public void deleteRule(List<String> ids) {
        checkIdsNotEmpty(ids);
        List<Rule> rules = ruleRepository.findAll(ids);
        ruleRepository.delete(rules);
    }

    @Override
    public Rule findByCode(String code) {
        return ruleRepository.findByCode(code);
    }

    @Transactional
    @Override
    public void deployToBpmEngine(List<String> ids) {
        ids.forEach(this::deployToBpmEngine);
    }

    private void deployToBpmEngine(String id) {
        Rule rule = ruleRepository.getOne(id);
        if (rule != null) {
            repositoryService.createDeployment()
                    .addInputStream(rule.getCode() + ".drl", new ByteArrayInputStream(Base64.getDecoder().decode(rule.getRules())))
                    .deploy();
        }
    }

    /**
     * 检查Code约束条件，不能重复
     *
     * @param rule
     */
    private void checkCodeConstraints(Rule rule) {
        if (rule.isNew()) {
            Assert.isNull(ruleRepository.findByCode(rule.getCode()), "编码不能重复！");
        } else {
            Optional.ofNullable(ruleRepository.findByCode(rule.getCode()))
                    .filter(r -> !r.getId().equals(rule.getId()))
                    .ifPresent(r -> {
                        throw new IllegalArgumentException("编码不能重复！");
                    });
        }
    }
}
