package com.huigou.topsun.sap.statsIndicators.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.sap.common.DefaultHttpClient;
import com.huigou.topsun.sap.common.domain.Message;
import com.huigou.topsun.sap.common.serializer.MessageCodec;
import com.huigou.topsun.sap.statsIndicators.application.SapStatsIndicatorsApplication;
import com.huigou.topsun.sap.statsIndicators.domain.SapStatsIndicators;
import com.huigou.topsun.sap.statsIndicators.domain.SapStatsIndicatorsDetail;
import com.huigou.topsun.sap.statsIndicators.domain.query.SapStatsIndicatorsDetailQueryRequest;
import com.huigou.topsun.sap.statsIndicators.domain.query.SapStatsIndicatorsQueryRequest;
import com.huigou.topsun.sap.statsIndicators.repository.SapStatsIndicatorsDetailRepository;
import com.huigou.topsun.sap.statsIndicators.repository.SapStatsIndicatorsRepository;
import com.huigou.topsun.util.MyBaseUtil;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.util.ClassHelper;

import com.huigou.util.SDO;
import lombok.SneakyThrows;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.beanutils.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.beans.IntrospectionException;
import java.beans.Introspector;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("sapStatsIndicatorsApplication")
public class SapStatsIndicatorsApplicationImpl  extends FlowBroker implements SapStatsIndicatorsApplication {

    @Autowired
    private SapStatsIndicatorsRepository sapStatsIndicatorsRepository;
    @Autowired
    private SapStatsIndicatorsDetailRepository sapStatsIndicatorsDetailRepository;

    @Autowired
    DefaultHttpClient defaultHttpClient;
    @Autowired
    MessageCodec messageCodec;

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

        SapStatsIndicators sapStatsIndicators = getBizEntity(SapStatsIndicators.class);
        if (sapStatsIndicators.isNew()) {
            sapStatsIndicators.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            sapStatsIndicators = (SapStatsIndicators) commonDomainService.loadAndFillinProperties(sapStatsIndicators);
        }
        sapStatsIndicators = sapStatsIndicatorsRepository.save(sapStatsIndicators);

        SDO sdo = this.getBizAndApprovalData();
        String statsIndicatorsDetailJSON = sdo.getString("statsIndicatorsDetail");
        ObjectMapper objectMapper = new ObjectMapper();
        List<SapStatsIndicatorsDetail> statsIndicatorsDetailList = objectMapper.readValue(statsIndicatorsDetailJSON, new TypeReference<List<SapStatsIndicatorsDetail>>() {});

        List<SapStatsIndicatorsDetail> allStatsIndicatorsDetail = sapStatsIndicatorsDetailRepository.findAllByStatsIndicatorsId(sapStatsIndicators.getId());
        if (!allStatsIndicatorsDetail.isEmpty()) {
            sapStatsIndicatorsDetailRepository.deleteInBatch(allStatsIndicatorsDetail);
        }
        for (SapStatsIndicatorsDetail statsIndicatorsDetail : statsIndicatorsDetailList) {
            statsIndicatorsDetail.setStatsIndicatorsDetailId(null);
            statsIndicatorsDetail.setStatsIndicatorsId(sapStatsIndicators.getId());
            sapStatsIndicatorsDetailRepository.save(statsIndicatorsDetail);
        }
        return sapStatsIndicators.getId();
    }


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


    /**
     * 流程实例结束
     * @param delegateExecution
     */
    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        SapStatsIndicators sapStatsIndicators = sapStatsIndicatorsRepository.findOne(bizId);
        sapStatsIndicators.setStatusId(status.getId());
        sapStatsIndicatorsRepository.save(sapStatsIndicators);

        //审核完成、远程调用sap接口

        List<SapStatsIndicatorsDetail> all = sapStatsIndicatorsDetailRepository.findAllByStatsIndicatorsId(bizId);
        List<Map<String,Object>> list = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = MyBaseUtil.convertToMap(sapStatsIndicators);
        //封装参数
        for (SapStatsIndicatorsDetail sapStatsIndicatorsDetail : all) {
            Map<String,Object> detailMap = objectMapper.convertValue(sapStatsIndicatorsDetail, Map.class);
            map.put("item",detailMap);
            list.add(map);
        }

        //三次失败抛出异常
        int retries = 0;
        boolean success = false;
        String url ="http://192.168.3.109:8000/sap/bc/erp_ep/cud_kb31n/kb31n?sap-client=200";
        while (!success && retries < 3) {
            try {
                String execute = defaultHttpClient.execute(list,url);
                TypeReference<List<Map<String, Object>>> typeRef = new TypeReference<List<Map<String, Object>>>() {};
                List<Map<String, Object>> mapList = objectMapper.readValue(execute, typeRef);
                Map<String, Object> resMap = mapList.get(0);
                //Message message = messageCodec.deserialze(execute);
                //Map<String, Object> body = message.getBody();
                if ("s".equals(resMap.get("TYPE"))) {
                    success = true;
                } else {
                    retries++;
                }
            } catch (IOException e) {
                throw new RuntimeException("sap服务器无响应请稍后再试！");
            }
        }

        if (!success) {
            throw new RuntimeException("远程调用SAP接口失败");
        }
    }

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

    /**
     * @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();
            SapStatsIndicators sapStatsIndicators = sapStatsIndicatorsRepository.findOne(bizId);
            sapStatsIndicators.setStatusId(BizBillStatus.APPLYING.getId());
            sapStatsIndicatorsRepository.save(sapStatsIndicators);
        }
    }

    @Override
    public SapStatsIndicators loadSapStatsIndicatorsById(String id) {
        return sapStatsIndicatorsRepository.findOne(id);
    }

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


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void deleteStatsIndicatorsById(String id) {
        List<SapStatsIndicatorsDetail> all = sapStatsIndicatorsDetailRepository.findAllByStatsIndicatorsId(id);
        sapStatsIndicatorsDetailRepository.deleteInBatch(all);
        sapStatsIndicatorsRepository.delete(id);

    }

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


}