package com.huigou.topsun.sap.statsIndicators.application.impl;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.huigou.data.domain.model.CommonDomainConstants;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.data.query.model.QueryModel;
import com.huigou.topsun.sap.common.DefaultHttpClient;
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.TmpStatsIndicatorsDetailImportDate;
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.sap.statsIndicators.repository.TmpStatsIndicatorsDetailImportDateRepository;
import com.huigou.topsun.sap.suppliers.domain.SuppliersInfo;
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.DateUtil;
import com.huigou.util.SDO;
import lombok.SneakyThrows;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
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 org.springframework.util.Assert;


import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
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
    private SapStatsIndicatorsResultRepository sapStatsIndicatorsResultRepository;

    @Autowired
    DefaultHttpClient defaultHttpClient;
    @Autowired
    MessageCodec messageCodec;
    @Autowired
    private TmpStatsIndicatorsDetailImportDateRepository importDateRepository;


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

    /**
     * 设置任务名称
     */
    @Override
    protected void setTaskDescription(DelegateTask delegateTask) {
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        delegateTask.setDescription(this.getApprovalSubjectName(bizId));
    }

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        SapStatsIndicators statsIndicators = this.sapStatsIndicatorsRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", statsIndicators.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", "统计指标过账", statsIndicators.getBillCode(), fillinDateStr);
    }

    /**
     * 流程撤销事件
     **/
    @Override
    protected void onRecallProcessInstance(DelegateExecution delegateExecution) {
        String bizId = delegateExecution.getProcessBusinessKey();
        // 修改单据状态为申请
        updateStatus(bizId, BizBillStatus.APPLYING);
    }

    /**
     * 任务完成前执行
     */
    @Override
    protected void onBeforeComplete(DelegateTask delegateTask) {
        super.onBeforeComplete(delegateTask);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        updateStatus(bizId, BizBillStatus.APPROVING);
    }

    /**
     * 回收事件
     **/
    @Override
    protected void onWithdraw(DelegateTask delegateTask, String destActivityId) {
        super.onWithdraw(delegateTask, destActivityId);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        if (destActivityId.equalsIgnoreCase("apply")) {
            updateStatus(bizId, BizBillStatus.APPLYING);
        }
    }

    @Transactional
    private void updateStatus(String bizId, BizBillStatus status) {
        Assert.hasText(bizId, CommonDomainConstants.ID_NOT_BLANK);
        this.commonDomainService.updateStatus(SapStatsIndicators.class, bizId, status.getId());
    }

    /**
     * 流程实例结束
     *
     * @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");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, query);
        queryModel.putDictionary("status",BizBillStatus.getMap());
        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }


    @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<>();
        Map<String, Object> map = MyBaseUtil.convertToMap(sapStatsIndicators,true);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if (sapStatsIndicators.getBldat() !=null){
            String bldat = dateFormat.format(sapStatsIndicators.getBldat());
            map.put("BLDAT",bldat);
        }
        if (sapStatsIndicators.getBudat() != null){
            String budat = dateFormat.format(sapStatsIndicators.getBudat());
            map.put("BUDAT",budat);
        }
        //封装参数
        for (SapStatsIndicatorsDetail sapStatsIndicatorsDetail : all) {
            String stagr = sapStatsIndicatorsDetail.getStagr();
            sapStatsIndicatorsDetail.setStagr(stagr.toUpperCase());
            Map<String, Object> detailMap = MyBaseUtil.convertToMap(sapStatsIndicatorsDetail,true);
            list.add(detailMap);
        }
        map.put("ITEM", list);
        String url = "cud_kb31n/kb31n";
        SapStatsIndicatorsResult sapStatsIndicatorsResult = new SapStatsIndicatorsResult();
        try {
            String result = defaultHttpClient.execute(map, url);
            List<SapStatsIndicatorsResult> resultList = JSONObject.parseArray(result,SapStatsIndicatorsResult.class);
            //List<SapStatsIndicatorsResult> resultList = objectMapper.readValue(result, new TypeReference<List<SapStatsIndicatorsResult>>() {});

            sapStatsIndicatorsResult = resultList.get(0);

            if (!"S".equals(sapStatsIndicatorsResult.getTYPE())) {
                throw new RuntimeException("数据传输失败，"+ sapStatsIndicatorsResult.getMESSAGE());
            }
        } catch (IOException e) {
            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);
        }
    }

    @Override
    public List<TmpStatsIndicatorsDetailImportDate> importExcelData(String batchNumber) {
        List<TmpStatsIndicatorsDetailImportDate>  dataList = importDateRepository.findByBatchNumber(batchNumber);
        return dataList;
    }
}