package com.huigou.topsun.proofing.application.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.topsun.product.domain.ProductPublishedConf;
import com.huigou.topsun.product.repository.ProductPublishedConfRepository;
import com.huigou.topsun.proofing.application.ProofingApplyApplication;

import com.huigou.topsun.proofing.domain.model.proofingApply.*;
import com.huigou.topsun.proofing.domain.model.proofingMake.ProofingMakeProcess;
import com.huigou.topsun.proofing.domain.query.ProofingApplyQuery;
import com.huigou.topsun.proofing.domain.vo.ProofingApplyAndLookedVo;

import com.huigou.topsun.proofing.repository.ProofingApplyLookedRepository;
import com.huigou.topsun.proofing.repository.ProofingApplyProcessRepository;
import com.huigou.topsun.proofing.repository.ProofingApplyRepository;

import com.huigou.topsun.proofing.repository.ProofingApplyTechnologyRepository;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.util.ClassHelper;
import com.huigou.util.SDO;
import com.huigou.util.StringUtil;
import lombok.SneakyThrows;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author yonghuan
 */
@Service("proofingApplyApplication")
public class ProofingApplyApplicationImpl extends FlowBroker implements ProofingApplyApplication {

    @Autowired
    private ProofingApplyRepository proofingApplyRepository;
    @Autowired
    private ProductPublishedConfRepository productPublishedConfRepository;
    @Autowired
    private ProofingApplyLookedRepository proofingApplyLookedRepository;
    @Autowired
    private ProofingApplyTechnologyRepository proofingTechnologyRepository;
    @Autowired
    private ProofingApplyProcessRepository proofingApplyProcessRepository;


    @Override
    public ProofingApplyBaseInfo loadProofingApplyById(String id) {
        return proofingApplyRepository.findOne(id);
    }

    @Override
    public Map<String, Object> slicedQuery(ProofingApplyQuery query) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "slicedQuery");
        return this.sqlExecutorDao.executeSlicedQuery(queryDescriptor,query);
    }

    @SneakyThrows
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        ProofingApplyBaseInfo proofingApply = getBizEntity(ProofingApplyBaseInfo.class);

        SDO sdo = this.getBizAndApprovalData();
        String technologyJSON = sdo.getString("technology");
        String processJSON = sdo.getString("process");
        ObjectMapper objectMapper = new ObjectMapper();
        proofingApplyTechnology proofingTechnology = objectMapper.readValue(technologyJSON, proofingApplyTechnology.class);
        List<ProofingApplyProcess> ProcessList = objectMapper.readValue(processJSON, new TypeReference<List<ProofingApplyProcess>>() {});
        ProofingApplyLooked proofingApplyLooked = getBizEntity(ProofingApplyLooked.class);

        if (proofingApply.isNew()) {
            proofingApply.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            proofingApply = (ProofingApplyBaseInfo) commonDomainService.loadAndFillinProperties(proofingApply);
        }
        String id = UUID.randomUUID().toString().replace("-", "");
        proofingApply.setProofingApplyId(id);
        proofingApply.setProofingApplyApplicationStatus(StringUtil.isBlank(proofingApply.getProofingApplyNgReReason())?"normal":"cancel");
        proofingApply = proofingApplyRepository.save(proofingApply);

        proofingApplyLooked.setProofingApplyId(proofingApply.getProofingApplyId());
        proofingApplyLookedRepository.save(proofingApplyLooked);

        proofingTechnology.setProofingApplyId(proofingApply.getProofingApplyId());
        proofingTechnology = proofingTechnologyRepository.save(proofingTechnology);

        for (ProofingApplyProcess proofingApplyProcess : ProcessList) {
            proofingApplyProcess.setProofingApplyTechnologyId(proofingTechnology.getProofingApplyTechnologyId());
            proofingApplyProcessRepository.save(proofingApplyProcess);
        }

        return proofingApply.getId();
    }


    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        return ClassHelper.toMap(proofingApplyRepository.getOne(bizId));
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        ProofingApplyBaseInfo proofingApply = proofingApplyRepository.findOne(bizId);
        proofingApply.setStatusId(status.getId());
        proofingApplyRepository.save(proofingApply);
    }

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        ProofingApplyBaseInfo proofingApply = proofingApplyRepository.findOne(bizId);
        proofingApply.setStatusId(BizBillStatus.ABORTED.getId());
        proofingApplyRepository.save(proofingApply);
    }

    /**
     * @param delegateTask
     * @param destActivityId 回退到的目标节点id
     */
    @Override
    protected void onBack(DelegateTask delegateTask, String destActivityId) {
        super.onBack(delegateTask, destActivityId);
        if ("Apply".equalsIgnoreCase(destActivityId)) {
            String bizId = delegateTask.getExecution().getProcessBusinessKey();
            ProofingApplyBaseInfo proofingApply = proofingApplyRepository.findOne(bizId);
            proofingApply.setStatusId(BizBillStatus.APPLYING.getId());
            proofingApplyRepository.save(proofingApply);
        }
    }


    public ProofingApplyAndLookedVo getProofingApplyByProofingApplyNo(String proofingApplyNo) {
        QueryDescriptor queryDescriptor =  this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "queryProofingApplyAndProductQuery");
        ProofingApplyAndLookedVo proofingApplyAndLookedVo = this.sqlExecutorDao.queryToObject(queryDescriptor.getSql(), ProofingApplyAndLookedVo.class, proofingApplyNo);
        ProductPublishedConf productPublishedConf = productPublishedConfRepository.getProductPublishedConfByProductId(proofingApplyAndLookedVo.getProductId());
        if(productPublishedConf!=null){
            BeanUtils.copyProperties(productPublishedConf,proofingApplyAndLookedVo);
      }
        return proofingApplyAndLookedVo;
    }

    /**
     * 映射打样制造和打样申请 除前缀不一样的字段
     * @param proofingApply
     * @throws IllegalAccessException
     */
    public void a(ProofingApplyAndLookedVo proofingApply) throws IllegalAccessException {
        Map<String, Object> proofingMake = new HashMap<>();

        Class<?> proofingApplyClass = proofingApply.getClass();
        Field[] fields = proofingApplyClass.getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            Object value = field.get(proofingApply);
            String proofingMakeName = name.replaceFirst("^proofingApply", "proofingMake");
            proofingMake.put(proofingMakeName, value);
        }

    }

    @Override
    public ProofingApplyBaseInfo selectProofingApplyByProofingApplyNo(String proofingApplyNo) {
        return proofingApplyRepository.findByProofingApplyNo(proofingApplyNo);
    }


}
