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

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huigou.cache.DictUtil;
import com.huigou.cache.SystemCache;
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.coderule.domain.model.CodeRule;
import com.huigou.topsun.base.coderule.repository.CodeRuleRepository;
import com.huigou.topsun.sap.common.HttpClient;
import com.huigou.topsun.sap.common.application.SapMutualEpLogApplication;
import com.huigou.topsun.sap.costReimbursement.domain.SapCostReimbursement;
import com.huigou.topsun.sap.purchase.domain.SapPurchase;
import com.huigou.topsun.sap.purchaseInfoRecord.application.SapPurchaseInfoRecordApplication;
import com.huigou.topsun.sap.purchaseInfoRecord.application.SapPurchaseInfoRecordItemApplication;
import com.huigou.topsun.sap.purchaseInfoRecord.domain.SapPurchaseInfoRecord;
import com.huigou.topsun.sap.purchaseInfoRecord.domain.SapPurchaseInfoRecordItem;
import com.huigou.topsun.sap.common.domain.SapResult;
import com.huigou.topsun.sap.purchaseInfoRecord.domain.query.SapPurchaseInfoRecordQueryRequest;
import com.huigou.topsun.sap.purchaseInfoRecord.domain.vo.SapPurchaseInfoRecordCancelVo;
import com.huigou.topsun.sap.purchaseInfoRecord.domain.vo.SapPurchaseInfoRecordItemVo;
import com.huigou.topsun.sap.purchaseInfoRecord.repository.SapPurchaseInfoRecordItemRepository;
import com.huigou.topsun.sap.purchaseInfoRecord.repository.SapPurchaseInfoRecordRepository;
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.StringUtil;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Auther: xin.lu
 * @Date: 2024/02/28/15:40
 * @Description:
 */
@Service("sapPurchaseInfoRecordApplication")
public class SapPurchaseInfoRecordApplicationImpl extends FlowBroker implements SapPurchaseInfoRecordApplication {

    @Autowired
    private SapPurchaseInfoRecordRepository sapPurchaseInfoRecordRepository;
    @Autowired
    private SapPurchaseInfoRecordItemApplication sapPurchaseInfoRecordItemApplication;
    @Resource
    private HttpClient httpClient;
    @Autowired
    SapMutualEpLogApplication sapMutualEpLogApplication;
    @Autowired
    private CodeRuleRepository codeRuleRepository;
    @Autowired
    private SapPurchaseInfoRecordItemRepository sapPurchaseInfoRecordItemRepository;

    @Transactional
    @Override
    public String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        SapPurchaseInfoRecord sapPurchaseInfoRecord = getBizEntity(SapPurchaseInfoRecord.class);
        if (sapPurchaseInfoRecord.isNew()) {
            sapPurchaseInfoRecord.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            sapPurchaseInfoRecord = (SapPurchaseInfoRecord) commonDomainService.loadAndFillinProperties(sapPurchaseInfoRecord);
        }
        sapPurchaseInfoRecord = sapPurchaseInfoRecordRepository.save(sapPurchaseInfoRecord);
        List<SapPurchaseInfoRecordItem> sapPurchaseInfoRecordItems = getBizEntities(SapPurchaseInfoRecordItem.class, "sapPurchaseInfoRecordItems");
        sapPurchaseInfoRecordItemApplication.saveSapPurchaseInfoRecordItem(sapPurchaseInfoRecord.getId(),sapPurchaseInfoRecordItems);
        return sapPurchaseInfoRecord.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) {
        SapPurchaseInfoRecord infoRecord = this.sapPurchaseInfoRecordRepository.findOne(bizId);
        String title = "";
        if ("new".equals(infoRecord.getFlag())){
            title = "新建-";
        }else if ("update".equals(infoRecord.getFlag())){
            title = "修改-";
        }else if ("cancel".equals(infoRecord.getFlag())){
            title = "作废-";
        }
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", infoRecord.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)",title + "采购信息记录", infoRecord.getBillCode(), fillinDateStr);
    }
    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        return ClassHelper.toMap(sapPurchaseInfoRecordRepository.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(SapPurchaseInfoRecord.class, bizId, status.getId());
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        //super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        SapPurchaseInfoRecord sapPurchaseInfoRecord = sapPurchaseInfoRecordRepository.findOne(bizId);
        sapPurchaseInfoRecord.setStatusId(status.getId());
        sapPurchaseInfoRecordRepository.save(sapPurchaseInfoRecord);

        this.getSapPurchaseInfoRecordItemVo(sapPurchaseInfoRecord);
    }

    public void getSapPurchaseInfoRecordItemVo(SapPurchaseInfoRecord sapPurchaseInfoRecord){
        List<SapPurchaseInfoRecordItem> purchaseInfoRecordItemList = sapPurchaseInfoRecordItemApplication.findBySapPurchaseInfoRecordId(sapPurchaseInfoRecord.getId());
        purchaseInfoRecordItemList.forEach(sapPurchaseInfoRecordItem -> {
            SapPurchaseInfoRecordItemVo sapPurchaseInfoRecordItemVo = new SapPurchaseInfoRecordItemVo();
            BeanUtil.copyProperties(sapPurchaseInfoRecordItem,sapPurchaseInfoRecordItemVo);
            //sapPurchaseInfoRecordItemVo.setInfnr(sapPurchaseInfoRecord.getBillCode());
            //无物料号的基本单位默认订单价格单位
            if (StringUtil.isBlank(sapPurchaseInfoRecordItemVo.getMeins())){
                sapPurchaseInfoRecordItemVo.setMeins(sapPurchaseInfoRecordItemVo.getBprme());
            }
            if ("new".equals(sapPurchaseInfoRecord.getFlag())){
                //物料编码为空  排序字段 传SAP FYL+7位流水号
                if (StringUtils.isBlank(sapPurchaseInfoRecordItemVo.getMatnr())
                        &&StringUtils.isBlank(sapPurchaseInfoRecordItemVo.getSortl())) {
                    //物料描述赋值给短文本
                    sapPurchaseInfoRecordItemVo.setTxz01(sapPurchaseInfoRecordItem.getMaktx());
                    //根据供应商和物料组来查询是否推送成功过，如果成功过 则设置序号 并累加1
                    SapPurchaseInfoRecordQueryRequest query=new SapPurchaseInfoRecordQueryRequest();
                    query.setLifnr(sapPurchaseInfoRecordItem.getLifnr());
                    query.setMatkl(sapPurchaseInfoRecordItem.getMatkl());
                    synchronized(this) {
                        List<SapPurchaseInfoRecordItem> list=sapPurchaseInfoRecordItemApplication.querySapPurchaseInfoRecordItemByMaytkl(query);

                        //如果明细中有相同的供应商和物料组 ，成功后还没有写库时，需要重新计算list大小
                        List<SapPurchaseInfoRecordItem> sucessList = purchaseInfoRecordItemList.stream()
                                .filter(purchaseInfoRecordItem -> "S".equals(purchaseInfoRecordItem.getTYPE())
                                        && sapPurchaseInfoRecordItem.getLifnr().equals(purchaseInfoRecordItem.getLifnr())
                                        && sapPurchaseInfoRecordItem.getMatkl().equals(purchaseInfoRecordItem.getMatkl())
                                ).collect(Collectors.toList());
                        list.addAll(sucessList);
                        if (list.size()>0){
                            sapPurchaseInfoRecordItemVo.setSortl("FYL"+formatSerialNumber(list.size()+1,7));
                        }else {
                            sapPurchaseInfoRecordItemVo.setSortl("FYL"+formatSerialNumber(1,7));
                        }
                    }
                }
                sapPurchaseInfoRecordItem.setSortl(sapPurchaseInfoRecordItemVo.getSortl());
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            if (sapPurchaseInfoRecordItem.getDatab() !=null){
                String datab = dateFormat.format(sapPurchaseInfoRecordItem.getDatab());
                sapPurchaseInfoRecordItemVo.setDatab(datab);
            }
            if (sapPurchaseInfoRecordItem.getDatbi() != null){
                String datbi = dateFormat.format(sapPurchaseInfoRecordItem.getDatbi());
                sapPurchaseInfoRecordItemVo.setDatbi(datbi);
            }
            if ("0".equals(sapPurchaseInfoRecordItemVo.getLoekz())){
                sapPurchaseInfoRecordItemVo.setLoekz("");
            }

            if ("cancel".equals(sapPurchaseInfoRecord.getFlag())){
                //如果是作废，设置报价失效标志为X
                sapPurchaseInfoRecordItemVo.setZzf("X");
            }
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("businessType", "采购信息记录维护");
            resultMap.put("businessId", sapPurchaseInfoRecord.getId());
            resultMap.put("parameter", JSON.toJSONString(sapPurchaseInfoRecordItemVo));
            try {
                String url = SystemCache.getParameter("sap.PurchaseInfoRecord.url", String.class);
                String execute = httpClient.execute(sapPurchaseInfoRecordItemVo, url);
                List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
                SapResult sapResult = resultList.get(0);
                if (!"S".equals(sapResult.getTYPE())){
                    resultMap.put("TYPE", sapResult.getTYPE());
                    resultMap.put("MESSAGE", "数据传输失败，"+ sapResult.getMESSAGE());
                    throw new RuntimeException("数据传输失败，"+ sapResult.getMESSAGE());
                } else {
                    resultMap.put("TYPE", sapResult.getTYPE());
                    resultMap.put("MESSAGE", sapResult.getMESSAGE());
                }
                sapPurchaseInfoRecordItem.setInfnr(sapResult.getMESSAGE_V1());
                sapPurchaseInfoRecordItem.setTYPE(sapResult.getTYPE());
                sapPurchaseInfoRecordItem.setMESSAGE(sapResult.getMESSAGE());
                sapPurchaseInfoRecordItem.setKnumh(sapResult.getMESSAGE_V2());
            //    sapPurchaseInfoRecordItem.setInfnr();//回写信息记录编号   待确认 //？？？？？
                sapPurchaseInfoRecordItemApplication.save(sapPurchaseInfoRecordItem);
                this.markCancelRecordItems(sapPurchaseInfoRecordItem);
            } catch (IOException e) {
                resultMap.put("TYPE", "E");
                resultMap.put("MESSAGE", e.getMessage());
                throw new RuntimeException(e);
            }finally {
                sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
            }
        });
    }

    /**
     * 标记作废的采购信息记录明细
     * 根据采购信息记录号查询所有的采购信息记录明细，然后将不是最新的采购信息记录明细的作废标志设置为X
     * @param purchaseInfoRecordItem
     */
    public void markCancelRecordItems(SapPurchaseInfoRecordItem purchaseInfoRecordItem){
        sapPurchaseInfoRecordItemRepository.findByInfnr(purchaseInfoRecordItem.getInfnr()).forEach(sapPurchaseInfoRecordItem1 -> {
            if (!sapPurchaseInfoRecordItem1.getId().equals(purchaseInfoRecordItem.getId())
                    && purchaseInfoRecordItem.getWerks().equals(sapPurchaseInfoRecordItem1.getWerks())){
                sapPurchaseInfoRecordItem1.setCancelFlag("X");
                sapPurchaseInfoRecordItemRepository.save(sapPurchaseInfoRecordItem1);
            }
        });

    }

    private String formatSerialNumber(Integer serialNumber, int length) {
        String result = String.valueOf(serialNumber);
        Assert.isTrue(result.length() <= length, String.format("流水号长度超出限制，设置长度：%s，实际长度：%s。", length, result.length()));
        while (result.length() < length) {
            result = "0" + result;
        }
        return result;
    }

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

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

    @Override
    public Map<String, Object> slicedSapPurchaseInfoRecordList(SapPurchaseInfoRecordQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "sapPurchaseInfoRecordList");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status", BizBillStatus.getMap());
        queryModel.putDictionary("urzla", DictUtil.getDictionary("country"));
        queryModel.putDictionary("loekz", DictUtil.getDictionary("loekz"));
        queryModel.putDictionary("mwskz", DictUtil.getDictionary("purchaseMwskz"));
        queryModel.addCriteria(" order by fillin_date desc ");

        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }

    @Override
    public SapPurchaseInfoRecord loadSapPurchaseInfoRecord(String id) {
        return sapPurchaseInfoRecordRepository.findOne(id);
    }

    @Override
    public void cancelPurchaseRecord(String id) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("businessType", "作废采购信息记录");
        resultMap.put("businessId", id);
        resultMap.put("parameter", JSON.toJSONString(id));
        SapPurchaseInfoRecordItem recordItem = this.sapPurchaseInfoRecordItemRepository.findOne(id);
        SapPurchaseInfoRecordCancelVo cancelVo = new SapPurchaseInfoRecordCancelVo();
        BeanUtil.copyProperties(recordItem,cancelVo);
        cancelVo.setZzf("X");//删除标识
        try {
            String url = SystemCache.getParameter("sap.PurchaseInfoRecord.url", String.class);
            String execute = httpClient.execute(cancelVo, url);
            List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
            SapResult sapResult = resultList.get(0);
            if (!"S".equals(sapResult.getTYPE())){
                resultMap.put("TYPE", sapResult.getTYPE());
                resultMap.put("MESSAGE", "数据传输失败，"+ sapResult.getMESSAGE());
                throw new RuntimeException("数据传输失败，"+ sapResult.getMESSAGE());
            } else {
                resultMap.put("TYPE", sapResult.getTYPE());
                resultMap.put("MESSAGE", sapResult.getMESSAGE());
            }
            //recordItem.setInfnr(sapResult.getMESSAGE_V1());
            recordItem.setTYPE(sapResult.getTYPE());
            recordItem.setMESSAGE(sapResult.getMESSAGE());
            recordItem.setCancelFlag("X");
            sapPurchaseInfoRecordItemApplication.save(recordItem);
        } catch (IOException e) {
            resultMap.put("TYPE", "E");
            resultMap.put("MESSAGE", e.getMessage());
            throw new RuntimeException(e);
        }finally {
            sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
        }
    }

}
