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.SapStatsIndicatorsResult;
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.sap.statsIndicators.repository.SapStatsIndicatorsResultRepository;
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 com.mchange.v1.util.MapUtils;
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;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

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

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

    @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接口
        sendSapDate(bizId);

    }

    @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);
    }


    /**
     * 远程调用sap接口，传递数据
     *
     * @param bizId
     */
    public void sendSapDate(String bizId) {
        SapStatsIndicators sapStatsIndicators = sapStatsIndicatorsRepository.findOne(bizId);
        if (sapStatsIndicators.getStatusId() == BizBillStatus.APPLYING.getId()) {
            throw new RuntimeException("本数据未经审批完成！");
        }
        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);
        }
        String url = "cud_kb31n/kb31n";
        SapStatsIndicatorsResult sapStatsIndicatorsResult = null;
        try {
            String result = defaultHttpClient.execute(list, url);
            List<SapStatsIndicatorsResult> resultList = objectMapper.readValue(result, new TypeReference<List<SapStatsIndicatorsResult>>() {
            });

            sapStatsIndicatorsResult = resultList.get(0);

            if (!"s".equals(sapStatsIndicatorsResult.getType())) {
                throw new RuntimeException("数据传输失败，请稍后手动重试！");
            }
        } catch (IOException e) {
            if (sapStatsIndicatorsResult == null) {
                sapStatsIndicatorsResult = new SapStatsIndicatorsResult();
            }
            sapStatsIndicatorsResult.setType("A");
            throw new RuntimeException("sap服务器无响应请稍后手动重试！");
        } finally {
            SapStatsIndicatorsResult statsIndicatorsId = sapStatsIndicatorsResultRepository.findByStatsIndicatorsId(bizId);
            if(statsIndicatorsId!=null)sapStatsIndicatorsResultRepository.delete(statsIndicatorsId);
            sapStatsIndicatorsResult.setStatsIndicatorsId(bizId);
            sapStatsIndicatorsResultRepository.save(sapStatsIndicatorsResult);
        }
    }

}