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

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huigou.cache.DictUtil;
import com.huigou.data.domain.model.CommonDomainConstants;
import com.huigou.data.domain.query.QueryPageRequest;
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.domain.SapResult;
import com.huigou.topsun.sap.costReimbursement.domain.SapCostReimbursement;
import com.huigou.topsun.sap.nonProducePick.application.NonProducePickApplication;
import com.huigou.topsun.sap.nonProducePick.application.NonProducePickItemApplication;
import com.huigou.topsun.sap.nonProducePick.domain.NonProducePick;
import com.huigou.topsun.sap.nonProducePick.domain.NonProducePickItem;
import com.huigou.topsun.sap.nonProducePick.domain.query.NonProducePickQueryRequest;
import com.huigou.topsun.sap.nonProducePick.repository.NonProducePickRepository;
import com.huigou.topsun.sap.nonProducePick.vo.*;
import com.huigou.topsun.sap.purchase.domain.SapPurchase;
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.lang.StringUtils;
import org.springframework.beans.BeanUtils;
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.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: xin.lu
 * @Date: 2024/03/13/9:45
 * @Description:
 */
@Service("nonProducePickApplication")
public class NonProducePickApplicationImpl extends FlowBroker implements NonProducePickApplication {
    @Autowired
    private NonProducePickRepository nonProducePickRepository;
    @Autowired
    private NonProducePickItemApplication nonProducePickItemApplication;
    @Autowired
    private DefaultHttpClient httpClient;
    @Override
    public NonProducePick findNonProducePickById(String id) {
        return nonProducePickRepository.findOne(id);
    }

    @Override
    public void deleteNonProducePickById(List<String> ids) {
        ids.forEach(id->{
            nonProducePickRepository.delete(id);
        });
    }

    @Override
    public NonProducePick saveNonProducePick(NonProducePick nonProducePick) {
        return nonProducePickRepository.save(nonProducePick);
    }

    @Override
    public Map<String, Object> slicedNonProducePickList(NonProducePickQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "nonProducePick");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status",BizBillStatus.getMap());
        Map<String, Object> map = this.sqlExecutorDao.executeSlicedQuery(queryModel);
        return map;
    }

    @Override
    public void sendNonProducePickData(NonProducePick nonProducePick,String ztype) {
        //List<NonProducePickVo> nonProducePickVoList = new ArrayList<>();
        NonProducePickVo nonProducePickVo = new NonProducePickVo();
        nonProducePickVo.setRsnum(nonProducePick.getMessage());
        nonProducePickVo.setZtype(ztype);
        //审批通过，不传ztype，state传3
        if (StringUtil.isBlank(ztype)){
            nonProducePickVo.setState("3");
        }
        nonProducePickVo.setBster(DateUtil.getDateFormat("yyyyMMdd",nonProducePick.getFillinDate()));
        nonProducePickVo.setWerks(nonProducePick.getWerks());
        nonProducePickVo.setUsnam(nonProducePick.getPersonMemberName());
        nonProducePickVo.setKostl(nonProducePick.getKostl());
        nonProducePickVo.setAufnr(nonProducePick.getAufnr());
        //若填写了成本中心，领料采用移动类型201；填写了内部订单，领料采用移动类型261，两者不可并存，SAP发起的刀工模板具领料采用移动类型Z01
        if (StringUtil.isNotBlank(nonProducePick.getKostl())){
            //根据BPM传过来的成本中心编码：KOSTL（如：1000E13000，1000F61305）
            //，-->CSKS- KOSTL --> CSKS-KOSAR，
            //1、如果CSKS-KOSAR=F或G，就用移动类型201，
            //2、如果CSKS-KOSAR=E或L或V，就用移动类型901，
            if (nonProducePick.getKostl().contains("F") || nonProducePick.getKostl().contains("G")){
                nonProducePickVo.setBwart("201");
            } else if (nonProducePick.getKostl().contains("E") || nonProducePick.getKostl().contains("L") || nonProducePick.getKostl().contains("V")){
                nonProducePickVo.setBwart("901");
            }
        } else if (StringUtil.isNotBlank(nonProducePick.getAufnr())) {
            nonProducePickVo.setBwart("261");
        }

        List<NonProducePickItem> pickItemList = nonProducePickItemApplication.findByNonProducePickId(nonProducePick.getId());
        List<NonProducePickItemVo> pickItemVoList = pickItemList.stream().map(pickItem -> {
            NonProducePickItemVo nonProducePickItemVo = new NonProducePickItemVo();
            BeanUtils.copyProperties(pickItem, nonProducePickItemVo);
            nonProducePickItemVo.setWerks(nonProducePick.getWerks());
            nonProducePickItemVo.setErfme(pickItem.getMeins());
            nonProducePickItemVo.setResItem(pickItem.getRspos());
            nonProducePickItemVo.setZtext(DictUtil.getDictionaryDetailText("used",pickItem.getUsed()));
            return nonProducePickItemVo;
        }).collect(Collectors.toList());
        nonProducePickVo.setItems(pickItemVoList);
        //nonProducePickVoList.add(nonProducePickVo);
        try {
            String execute = httpClient.execute(nonProducePickVo, "cud_ro/cud_ro");
            List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
            SapResult sapResult = resultList.get(0);
            if (!"S".equals(sapResult.getTYPE())){
                throw new RuntimeException("数据传输失败，"+ sapResult.getMESSAGE());
            }
            nonProducePick.setType(sapResult.getTYPE());
            if ("Y".equals(ztype)){
                nonProducePick.setMessage(sapResult.getMESSAGE_V1());
            }
//            else if ("N".equals(ztype)){
//                nonProducePick.setMessage(sapResult.getMESSAGE());
//            }else if (StringUtil.isBlank(ztype)){
//                nonProducePick.setMessage(sapResult.getMESSAGE());
//            }
            nonProducePickRepository.save(nonProducePick);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void chargeOff(String message) {
        //TODO
    }

    @Override
    public List<PDANonProducePickItemVo> getNonProducePick(List<String> rsnums) {
        String join = StringUtils.join(rsnums, ",");
        NonProducePickQueryRequest queryRequest = new NonProducePickQueryRequest();
        queryRequest.setMessage(join);
        QueryPageRequest pageRequest = new QueryPageRequest();
        pageRequest.setPageSize(200);
        pageRequest.setPageIndex(1);
        queryRequest.setPageModel(pageRequest);
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "nonProducePickByRsnums");
        Map<String, Object> map = this.sqlExecutorDao.executeSlicedQuery(queryDescriptor, queryRequest);
        List<Map<String, Object>> maps = (List<Map<String, Object>>) map.get("Rows");
        List<PDANonProducePickItemVo> itemVoList = maps
                .stream()
                .map(map1 -> {
                    PDANonProducePickItemVo pdaNonProducePickItemVo = ClassHelper.fromMap(PDANonProducePickItemVo.class, map1);
                    String used = pdaNonProducePickItemVo.getUsed();
                    used = used.replace("C","R");
                    pdaNonProducePickItemVo.setUsed(used);
                    return pdaNonProducePickItemVo;
                }).collect(Collectors.toList());
        return itemVoList;
    }

    @Override
    public void backNonProducePick(PDABackPickVo requestBody) {
        List<PDABackPickItemVo> items = requestBody.getData();
        items.forEach(item -> {
            NonProducePick producePick = nonProducePickRepository.findByMessage(item.getMessage());
            if (producePick == null){
                throw new RuntimeException("预留号不存在："+item.getMessage());
            }
            List<NonProducePickItem> itemList = nonProducePickItemApplication.findByNonProducePickId(producePick.getId());
            itemList.forEach(pickItem -> {
                if (pickItem.getRspos().equals(item.getRspos())){

                    //如果冲销凭证号是空直接赋值，如果有值，以逗号拼接
                    if (StringUtil.isBlank(pickItem.getChargeOffMessage())){
                        pickItem.setChargeOffMessage(item.getChargeOffMessage());
                    }else {
                        if (!pickItem.getChargeOffMessage().contains(item.getChargeOffMessage())){
                            pickItem.setChargeOffMessage(pickItem.getChargeOffMessage()+","+item.getChargeOffMessage());
                        }
                    }
                    //如果实际退料数量是空直接赋值，如果有值，进行累加
                    if (pickItem.getZerfmg() == null){
                        pickItem.setZerfmg(item.getZerfmg());
                    }else {
                        BigDecimal zerfmg1 = pickItem.getZerfmg();
                        BigDecimal zerfmg = item.getZerfmg();
                        pickItem.setZerfmg(zerfmg1.add(zerfmg));
                    }
                    if (StringUtil.isBlank(item.getCheckedBox())){
                        //实际退料数量大于等于退料数量标识完结Y，否则N
                        BigDecimal zerfmg = pickItem.getZerfmg();
                        BigDecimal backNum = pickItem.getBackNum();
                        if (zerfmg.compareTo(backNum) >= 0){
                            pickItem.setCheckedBox("Y");
                        }else {
                            pickItem.setCheckedBox("N");
                        }
                    }else {
                        pickItem.setCheckedBox(item.getCheckedBox());
                    }
                    nonProducePickItemApplication.updateNonProducePickItem(pickItem);
                }
            });
        });
    }

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        NonProducePick nonProducePick = getBizEntity(NonProducePick.class);
        List<NonProducePickItem> nonProducePickItems = getBizEntities(NonProducePickItem.class, "items");
        if (nonProducePick.isNew()) {
            nonProducePick.setStatusId(BizBillStatus.APPLYING.getId());
            //根据工厂。物料，单位检查可用数量
        } else {
            nonProducePick = (NonProducePick) commonDomainService.loadAndFillinProperties(nonProducePick);
        }
        //还未创建预留单之前都需要校验数量
//        if (StringUtil.isBlank(nonProducePick.getMessage())){
//            this.checkNonProducePickNum(nonProducePickItems, nonProducePick.getWerks());
//        }
        nonProducePick = nonProducePickRepository.save(nonProducePick);
        nonProducePickItemApplication.saveNonProducePickItems(nonProducePick.getId(),nonProducePickItems);
        return nonProducePick.getId();
    }

    public void checkNonProducePickNum(List<NonProducePickItem> nonProducePickItems,String werks){
        List<CheckNonProducePickItemNumVo> collect = nonProducePickItems
                .stream()
                .map(nonProducePickItem -> {
                    CheckNonProducePickItemNumVo checkNonProducePickItemNumVo = new CheckNonProducePickItemNumVo();
                    BeanUtils.copyProperties(nonProducePickItem, checkNonProducePickItemNumVo);
                    checkNonProducePickItemNumVo.setWerks(werks);
                    return checkNonProducePickItemNumVo;
                }).collect(Collectors.toList());
        try {
            //http://192.168.3.109:8000/sap/bc/erp_ep/mm_check?sap-client=300
            String execute = httpClient.execute(collect, "mm_check");
            List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
            SapResult sapResult = resultList.get(0);
            if (!"S".equals(sapResult.getTYPE())){
                List<String> stringList = resultList.stream().map(SapResult::getMESSAGE).collect(Collectors.toList());
                String message = String.join(";", stringList);
                throw new RuntimeException(message);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        return ClassHelper.toMap(nonProducePickRepository.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);
        NonProducePick nonProducePick = nonProducePickRepository.findOne(bizId);
        //第一次提交推送到SAP
        if (StringUtil.isBlank(nonProducePick.getMessage()) && this.getApprovalParameter().isAdvanceProcessAction()){
            this.sendNonProducePickData(nonProducePick,"Y");
        }
    }

    /**
     * 回收事件
     **/
    @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(NonProducePick.class, bizId, status.getId());
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        //取消待办任务办结提醒
        //super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        NonProducePick nonProducePick = nonProducePickRepository.findOne(bizId);
        this.sendNonProducePickData(nonProducePick,"");
        nonProducePick.setStatusId(status.getId());
        nonProducePickRepository.save(nonProducePick);
    }

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        NonProducePick nonProducePick = nonProducePickRepository.findOne(bizId);
        nonProducePick.setStatusId(BizBillStatus.ABORTED.getId());
        nonProducePickRepository.save(nonProducePick);
        //终止推送到SAP
        if (StringUtil.isNotBlank(nonProducePick.getMessage())){
            this.sendNonProducePickData(nonProducePick,"N");
        }
    }

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

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

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        NonProducePick producePick = this.nonProducePickRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", producePick.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", "其他物品领发料", producePick.getBillCode(), fillinDateStr);
    }
}
