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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huigou.cache.SystemCache;
import com.huigou.context.Operator;
import com.huigou.context.ThreadLocalUtil;
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.base.bsnMessage.appliction.MannualStartWorkApplication;
import com.huigou.topsun.sap.common.DefaultHttpClient;
import com.huigou.topsun.sap.common.application.SapMutualEpLogApplication;
import com.huigou.topsun.sap.productScrapApply.application.ProductScrapApplyApplication;
import com.huigou.topsun.sap.productScrapApply.application.ProductScrapApplyItemApplication;
import com.huigou.topsun.sap.productScrapApply.domain.ProductScrapApply;
import com.huigou.topsun.sap.productScrapApply.domain.ProductScrapApplyItem;
import com.huigou.topsun.sap.productScrapApply.domain.query.ProductScrapApplyQueryRequest;
import com.huigou.topsun.sap.productScrapApply.repository.ProductScrapApplyRepository;
import com.huigou.topsun.sap.productScrapApply.vo.ProductScrapApplyBackVo;
import com.huigou.topsun.sap.productScrapApply.vo.ProductScrapApplyVo;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.operator.OperatorApplication;
import com.huigou.uasp.bmp.opm.domain.model.org.Org;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.util.ClassHelper;
import com.huigou.util.DateUtil;
import com.huigou.util.StringUtil;
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.Transactional;
import org.springframework.util.Assert;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Auther: xin.lu
 * @Date: 2024/07/09/15:13
 * @Description:
 */
@Service("productScrapApplyApplication")
public class ProductScrapApplyApplicationImpl extends FlowBroker implements ProductScrapApplyApplication {
    @Autowired
    private ProductScrapApplyRepository productScrapApplyRepository;
    @Autowired
    private ProductScrapApplyItemApplication productScrapApplyItemApplication;
    @Autowired
    private OperatorApplication operatorApplication;
    @Autowired
    private MannualStartWorkApplication mannualStartWorkApplication;
    @Autowired
    private DefaultHttpClient defaultHttpClient;
    @Autowired
    private SapMutualEpLogApplication sapMutualEpLogApplication;

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        ProductScrapApply productScrapApply = getBizEntity(ProductScrapApply.class);
        if (productScrapApply.isNew()) {
            productScrapApply.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            productScrapApply = (ProductScrapApply) commonDomainService.loadAndFillinProperties(productScrapApply);
        }
        productScrapApply = productScrapApplyRepository.save(productScrapApply);
        List<ProductScrapApplyItem> productScrapApplyItems = getBizEntities(ProductScrapApplyItem.class, "productScrapApplyItems");
        productScrapApplyItemApplication.saveProductScrapApplyItems(productScrapApply.getId(),productScrapApplyItems);

        //String sapPurchaseVoJson = this.getSapPurchaseVoJson(productScrapApply);
        return productScrapApply.getId();
    }

    @Override
    protected void setTaskDescription(DelegateTask delegateTask) {
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        delegateTask.setDescription(this.getApprovalSubjectName(bizId));
    }

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        ProductScrapApply productScrapApply = this.productScrapApplyRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", productScrapApply.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)","物品报废申请与过账平台",productScrapApply.getBillCode() , fillinDateStr);
    }

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

    /**
     * 流程撤销事件
     **/
    @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
    protected void updateStatus(String bizId, BizBillStatus status) {
        Assert.hasText(bizId, CommonDomainConstants.ID_NOT_BLANK);
        this.commonDomainService.updateStatus(ProductScrapApply.class, bizId, status.getId());
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        //super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        ProductScrapApply productScrapApply = productScrapApplyRepository.findOne(bizId);
        sendSapData(productScrapApply,"3");//通过
        productScrapApply.setStatusId(status.getId());
        productScrapApplyRepository.save(productScrapApply);
    }

    public void sendSapData(ProductScrapApply productScrapApply,String status){
        List<ProductScrapApplyItem> itemList = productScrapApplyItemApplication.queryProductScrapApplyItems(productScrapApply.getId());
        ProductScrapApplyBackVo productScrapApplyBackVo = new ProductScrapApplyBackVo();
        productScrapApplyBackVo.setBillCode(productScrapApply.getBillCode());
        productScrapApplyBackVo.setZstatus(status);
        productScrapApplyBackVo.setZsanum(itemList.get(0).getZsanum());

        ObjectMapper objectMapper = new ObjectMapper();
        //http://192.168.3.109:8000/sap/bc/erp_ep/upd_ztmm004_std?sap-client=300
        String url = "upd_ztmm004_std";
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("businessType", "废品报废申请");
        resultMap.put("businessId", productScrapApply.getBillCode());
        resultMap.put("parameter", JSON.toJSONString(productScrapApplyBackVo));
        try {
            String result = defaultHttpClient.execute(productScrapApplyBackVo, url);
            List<Map<String, Object>> resultList = objectMapper.readValue(result, new TypeReference<List<Map<String, Object>>>() {});
            Map<String, Object> backMap = resultList.get(0);
            if (!"S".equals(backMap.get("TYPE"))) {
                throw new RuntimeException("数据传输失败，请稍后手动重试！"+backMap.get("MESSAGE"));
            } else {
                resultMap.put("TYPE", backMap.get("TYPE"));
                resultMap.put("MESSAGE", backMap.get("MESSAGE"));
            }
            productScrapApply.setType((String) backMap.get("TYPE"));
            productScrapApply.setMessage((String) backMap.get("MESSAGE"));
            productScrapApplyRepository.save(productScrapApply);
        } catch (Exception e) {
            resultMap.put("TYPE", "E");
            resultMap.put("MESSAGE", e.getMessage());
            throw new RuntimeException("数据传输失败请检查数据后重试！"+e.getMessage());
        }finally {
            sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
        }
    }

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        ProductScrapApply productScrapApply = productScrapApplyRepository.findOne(bizId);
        this.sendSapData(productScrapApply,"2");//拒绝
        productScrapApply.setStatusId(BizBillStatus.ABORTED.getId());
        productScrapApplyRepository.save(productScrapApply);
    }

    /**
     * @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();
            ProductScrapApply productScrapApply = productScrapApplyRepository.findOne(bizId);
            productScrapApply.setStatusId(BizBillStatus.APPLYING.getId());
            productScrapApplyRepository.save(productScrapApply);
        }
    }
    
    @Override
    public Map<String, Object> slicedProductScrapApplyList(ProductScrapApplyQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "productScrapApplyList");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status", BizBillStatus.getMap());
        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }

    @Override
    public ProductScrapApply loadProductScrapApply(String id) {
        return productScrapApplyRepository.findOne(id);
    }

    @Override
    public void saveProductScrapApplyVo(ProductScrapApply productScrapApply) {
        productScrapApplyRepository.save(productScrapApply);
    }

    @Override
    @Transactional
    public String saveProductScrapApplyVo(List<ProductScrapApplyVo> productScrapApplyVoListVo) {
        String productScrapApplyId = "";
        ProductScrapApply productScrapApply = new ProductScrapApply();
        String zuser1 = productScrapApplyVoListVo.get(0).getZuser1();
        //根据SAP传过来的创建人编码，映射流程发起人
        Org org = orgApplication.loadMainOrgByLoginName(zuser1);
        if (ObjectUtil.isNull(org)){
            String acceptPersonCode = SystemCache.getParameter("acceptPersonCode", String.class);
            org = orgApplication.loadMainOrgByLoginName(acceptPersonCode);
        }
        Operator operator = operatorApplication.createOperatorByPersonMemberId(org.getId());
        ThreadLocalUtil.putOperator(operator);
        //发起流程
        List<ProductScrapApplyItem> productScrapApplyItems =  new ArrayList<>();
        for (ProductScrapApplyVo productScrapApplyVo : productScrapApplyVoListVo) {
            ProductScrapApplyItem productScrapApplyItem = new ProductScrapApplyItem();
            BeanUtil.copyProperties(productScrapApplyVo,productScrapApplyItem);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            if (StringUtil.isNotBlank(productScrapApplyVo.getZdat())){
                try {
                    Date parse = dateFormat.parse(productScrapApplyVo.getZdat());
                    productScrapApplyItem.setZdat(parse);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
            productScrapApplyItems.add(productScrapApplyItem);
        }
        productScrapApplyId = mannualStartWorkApplication.startWorkflow(productScrapApply,PROCESS_DEFINITION_KEY,"productScrapApply");
        productScrapApplyItemApplication.saveProductScrapApplyItems(productScrapApplyId,productScrapApplyItems);
        productScrapApply = productScrapApplyRepository.findOne(productScrapApplyId);
        return productScrapApply.getBillCode();
    }
}
