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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
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.OrgUnit;
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.costReimbursement.domain.SapCostReimbursement;
import com.huigou.topsun.sap.purchase.domain.SapPurchase;
import com.huigou.topsun.sap.purchase.domain.SapPurchaseItem;
import com.huigou.topsun.sap.purchaseApproval.application.impl.SapPurchaseApprovalApplicationImpl;
import com.huigou.topsun.sap.purchaseOrder.application.SapPurchaseOrderApplication;
import com.huigou.topsun.sap.purchaseOrder.application.SapPurchaseOrderItemApplication;
import com.huigou.topsun.sap.purchaseOrder.domain.SapPurchaseOrder;
import com.huigou.topsun.sap.purchaseOrder.domain.SapPurchaseOrderItem;
import com.huigou.topsun.sap.purchaseOrder.domain.query.SapPurchaseOrderQueryRequest;
import com.huigou.topsun.sap.purchaseOrder.domain.vo.SapPurchaseOrderDto;
import com.huigou.topsun.sap.purchaseOrder.domain.vo.SapPurchaseOrderItemVo;
import com.huigou.topsun.sap.purchaseOrder.domain.vo.SapPurchaseOrderVo;
import com.huigou.topsun.sap.purchaseOrder.repository.SapPurchaseOrderRepository;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.fn.CodeGenerator;
import com.huigou.uasp.bmp.operator.OperatorApplication;
import com.huigou.uasp.bmp.opm.application.OrgApplication;
import com.huigou.uasp.bmp.opm.domain.model.org.Org;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.uasp.bpm.ProcessAction;
import com.huigou.uasp.bpm.ProcessStartModel;
import com.huigou.uasp.bpm.engine.application.WorkflowApplication;
import com.huigou.util.*;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
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 org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Auther: xin.lu
 * @Date: 2024/01/09/18:59
 * @Description:
 */
@Service("sapPurchaseOrderApplication")
public class SapPurchaseOrderApplicationImpl extends FlowBroker implements SapPurchaseOrderApplication {
    @Resource
    private SapPurchaseOrderRepository sapPurchaseOrderRepository;
    @Resource
    private SapPurchaseOrderItemApplication sapPurchaseOrderItemApplication;
    @Resource
    private OperatorApplication operatorApplication;
    @Autowired
    DefaultHttpClient defaultHttpClient;
    @Autowired
    SapPurchaseApprovalApplicationImpl sapPurchaseApprovalApplication;

    @Autowired
    private MannualStartWorkApplication mannualStartWorkApplication;
    @Autowired
    private OrgApplication orgApplication;

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        SDO sdo = this.getBizAndApprovalData();
        SapPurchaseOrder sapPurchaseOrder = getBizEntity(SapPurchaseOrder.class);
        if (sapPurchaseOrder.isNew()) {
            sapPurchaseOrder.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            sapPurchaseOrder = (SapPurchaseOrder) commonDomainService.loadAndFillinProperties(sapPurchaseOrder);
        }
        sapPurchaseOrder = sapPurchaseOrderRepository.save(sapPurchaseOrder);
//        SapPurchaseOrderItem sapPurchaseOrderItem = getBizEntity(SapPurchaseOrderItem.class);
//        if(sapPurchaseOrderItem!=null){
//            sapPurchaseOrderItem.setPurchaseOrderId(sapPurchaseOrder.getId());
//            sapPurchaseOrderItemApplication.saveSapPurchaseOrderItem(sapPurchaseOrderItem);
//        }
        return sapPurchaseOrder.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) {
        SapPurchaseOrder sapPurchaseOrder = this.sapPurchaseOrderRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", sapPurchaseOrder.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", sapPurchaseOrder.getBatxt(), sapPurchaseOrder.getEbeln(), fillinDateStr);
    }

    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例
        return ClassHelper.toMap(sapPurchaseOrderRepository.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();
        if (this.isApplyProcUnit(delegateTask) && this.getApprovalParameter().isAdvanceProcessAction()) {
            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(SapPurchaseOrder.class, bizId, status.getId());
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        SapPurchaseOrder sapPurchaseOrder = sapPurchaseOrderRepository.findOne(bizId);
        sapPurchaseOrder.setStatusId(status.getId());
        SapPurchaseOrder save = sapPurchaseOrderRepository.save(sapPurchaseOrder);
        this.sendSapDate(save, "Y");
    }


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

    /**
     * @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();
            SapPurchaseOrder sapPurchaseOrder = sapPurchaseOrderRepository.findOne(bizId);
            sapPurchaseOrder.setStatusId(BizBillStatus.APPLYING.getId());
            SapPurchaseOrder save = sapPurchaseOrderRepository.save(sapPurchaseOrder);
            //this.sendSapDate(save, "N");
            // 调用 onEnd 方法
//            DelegateExecution execution = delegateTask.getExecution();
//            onEnd(execution);
        }
    }

    @Override
    public Map<String, Object> slicedSapPurchaseOrderList(SapPurchaseOrderQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "sapPurchaseOrderList");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status", BizBillStatus.getMap());
        if (queryRequest.getBillCode() != null) {
            queryModel.addCriteria(" and t.bill_code like:billCode");
            queryModel.putLikeParam("billCode", queryRequest.getBillCode());
        }
        if (queryRequest.getEbeln() != null) {
            queryModel.addCriteria(" and t.ebeln like:ebeln");
            queryModel.putLikeParam("ebeln", queryRequest.getEbeln());
        }
        queryModel.addCriteria(" order by fillin_date desc ");
        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }

    @Override
    public SapPurchaseOrder loadSapPurchaseOrder(String id) {
        return sapPurchaseOrderRepository.findOne(id);
    }

    @Override
    @Transactional
    public void saveSapPurchaseOrderDto(SapPurchaseOrderDto sapPurchaseOrderDto) {
        SapPurchaseOrderVo sapPurchaseOrderVo = sapPurchaseOrderDto.getLsHeader();
        List<SapPurchaseOrder> purchaseOrders = sapPurchaseOrderRepository.findAllByEbeln(sapPurchaseOrderVo.getEbeln());
        String purchaseOrderId = "";
        //数据第一次接收，创建流程任务
            SapPurchaseOrder sapPurchaseOrder = new SapPurchaseOrder();
            BeanUtil.copyProperties(sapPurchaseOrderVo, sapPurchaseOrder);
        String ernam = sapPurchaseOrderVo.getErnam();
        Org org = orgApplication.loadMainOrgByLoginName(ernam);
        String acceptPersonCode = SystemCache.getParameter("acceptPersonCode", String.class);
        if (ObjectUtil.isNull(org)){
            org = orgApplication.loadMainOrgByLoginName(acceptPersonCode);
        }
        if (ObjectUtil.isNotNull(org)){
            Operator operator = operatorApplication.createOperatorByPersonMemberId(org.getId());
            ThreadLocalUtil.putOperator(operator);
        }else {
            //throw new RuntimeException("未找到采购订单创建人：" + ernam);
        }

        List<SapPurchaseOrderItemVo> ltItems = sapPurchaseOrderDto.getLtItems();
        List<SapPurchaseOrderItem> purchaseOrderItems = new ArrayList<>();
        String retpo = "";
        for (SapPurchaseOrderItemVo approvalItemVo : ltItems) {
            SapPurchaseOrderItem sapPurchaseApprovalItem = new SapPurchaseOrderItem();
            BeanUtil.copyProperties(approvalItemVo, sapPurchaseApprovalItem);
            purchaseOrderItems.add(sapPurchaseApprovalItem);
            if ("X".equals(approvalItemVo.getRetpo())){
                retpo = "X";
            }else {
                //审批要素不能为空，赋值E
                retpo = "E";
            }
        }
        sapPurchaseOrder.setRetpo(retpo);
            //初始化用户信息
          /*  String createdById = "5EEB2DC861694A65933CB4CE9A8D870A@C18E23AAAA6940E09DF7C122332C51E0";
            Operator operator = operatorApplication.createOperatorByPersonMemberId(createdById);
            sapPurchaseOrder.setDefaultValues(new OrgUnit(operator.getFullId(), operator.getFullName()));

            Map<String, Object> formData = BeanUtil.beanToMap(sapPurchaseOrder);
            String bizId = sapPurchaseApprovalApplication.startProcessInstance(SapPurchaseOrderApplication.PROCESS_DEFINITION_KEY, formData);
            sapPurchaseOrder.setId(bizId);
            //映射双方字段
            sapPurchaseOrder.setFillinDate(sapPurchaseOrderVo.getAedat());
            */
            //发起流程
           // String nextCode = codeGenerator.getNextCode("sapPurchaseOrder");
           // sapPurchaseOrder.setBillCode(nextCode);
           // sapPurchaseOrder =mannualStartWorkflow(sapPurchaseOrder);
          //  sapPurchaseOrder = this.sapPurchaseOrderRepository.save(sapPurchaseOrder);
          //  purchaseOrderId = sapPurchaseOrder.getId();
        if (CollectionUtils.isEmpty(purchaseOrders)) {
            //存在也新建 04.28注释的    05.11 把存在的作废掉
            purchaseOrderId=mannualStartWorkApplication.startWorkflow(sapPurchaseOrder,PROCESS_DEFINITION_KEY,"sapPurchaseOrder");
        } else {
            //将存在的作废掉   05.11 lxh
            for (SapPurchaseOrder purchaseOrder : purchaseOrders) {
                //终止状态不管
                //审批完成的，SAP撤审触发，终止审批完成的，并发起新的流程
                if (purchaseOrder.getStatusId() == BizBillStatus.COMPLETED.getId()){
                    purchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
                    purchaseOrderId=mannualStartWorkApplication.startWorkflow(sapPurchaseOrder,PROCESS_DEFINITION_KEY,"sapPurchaseOrder");
                }
                //在审批中，更新明细数据的（先删除，再新增）
                if (purchaseOrder.getStatusId() == BizBillStatus.APPROVING.getId() || purchaseOrder.getStatusId() == BizBillStatus.APPLYING.getId()){
                    List<SapPurchaseOrderItem> itemList = sapPurchaseOrderItemApplication.getPurchaseOrderItems(purchaseOrder.getId());
                    sapPurchaseOrderItemApplication.deletePurchaseOrderItems(itemList);
                    purchaseOrderId = purchaseOrder.getId();
                }
                this.sapPurchaseOrderRepository.save(purchaseOrder);
            }

            //数据第n次接收覆盖上一次数据
          /*    BeanUtil.copyProperties(sapPurchaseOrderVo, purchaseOrder);
            this.sapPurchaseOrderRepository.save(purchaseOrder);

            List<SapPurchaseOrderItem> purchaseOrderItems = sapPurchaseOrderItemApplication.getPurchaseOrderItems(purchaseOrder.getId());
            sapPurchaseOrderItemApplication.deletePurchaseOrderItems(purchaseOrderItems);
            purchaseOrderId = purchaseOrder.getId();*/
        }  //  lxh 04.28

        sapPurchaseOrderItemApplication.saveSapPurchaseOrderItems(purchaseOrderId, purchaseOrderItems);

    }


     /**
     * 远程调用sap接口，传递数据
     */
    public void sendSapDate(SapPurchaseOrder sapPurchaseOrder, String flag) {
        Map<String, Object> paramItem = new HashMap<>();
        paramItem.put("ebeln", sapPurchaseOrder.getEbeln());
        paramItem.put("BEDNR", sapPurchaseOrder.getBillCode());
        paramItem.put("frgkz", "10");
        paramItem.put("flag", flag);
        List<Map<String, Object>> paramList = new ArrayList<>();
        paramList.add(paramItem);
        Map<String, Object> param = new HashMap<>();
        param.put("MODE", "PO");
        param.put("DATA", paramList);

        ObjectMapper objectMapper = new ObjectMapper();
        String url = "pass_approval/approval";
        try {
            String result = defaultHttpClient.execute(param, url);
            List<Map<String, Object>> resultList = objectMapper.readValue(result, new TypeReference<List<Map<String, Object>>>() {
            });
            Map<String, Object> resultMap = resultList.get(0);
            if ("S".equals(resultMap.get("TYPE"))) {
                sapPurchaseOrder.setMsgId((String) resultMap.get("ID"));
                sapPurchaseOrder.setNumber((String) resultMap.get("NUMBER"));
                sapPurchaseOrder.setMsgType((String) resultMap.get("TYPE"));
                sapPurchaseOrder.setLogNo((String) resultMap.get("LOG_NO"));
                sapPurchaseOrder.setLogMsgNo((String) resultMap.get("LOG_MSG_NO"));
                sapPurchaseOrder.setMessage((String) resultMap.get("MESSAGE"));
                sapPurchaseOrder.setMessageV1((String) resultMap.get("MESSAGE_V1"));
                sapPurchaseOrder.setMessageV2((String) resultMap.get("MESSAGE_V1"));
                sapPurchaseOrder.setMessageV3((String) resultMap.get("MESSAGE_V1"));
                sapPurchaseOrder.setMessageV4((String) resultMap.get("MESSAGE_V1"));
                this.sapPurchaseOrderRepository.save(sapPurchaseOrder);
            } else {
                throw new RuntimeException("数据传输失败，请稍后手动重试！" + resultMap.get("MESSAGE"));
            }
        } catch (Exception e) {
            throw new RuntimeException("数据传输失败请检查数据后重试！" + e.getMessage());
        }
    }

    @Override
    public  String revokeApproval(String id){
        SapPurchaseOrder sapPurchaseOrder = this.sapPurchaseOrderRepository.findOne(id);
        if (sapPurchaseOrder.getStatusId()!=BizBillStatus.COMPLETED.getId()){
            throw new RuntimeException("审批完成的单据才能撤销！");
        }
        sapPurchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
        sapPurchaseOrderRepository.save(sapPurchaseOrder);
        List<SapPurchaseOrderItem> sapPurchaseOrderItemList=this.sapPurchaseOrderItemApplication.getPurchaseOrderItems(id);
        //发起流程
        SapPurchaseOrder newSapPurchaseOrder=new SapPurchaseOrder();
        ClassHelper.copyProperties(sapPurchaseOrder,newSapPurchaseOrder);
        newSapPurchaseOrder.setId("");

        String pId=mannualStartWorkApplication.startWorkflow(newSapPurchaseOrder,PROCESS_DEFINITION_KEY,"sapPurchaseOrder");
        newSapPurchaseOrder=this.sapPurchaseOrderRepository.findOne(pId);


        List<SapPurchaseOrderItem> newSapPurchaseOrderItemList=new ArrayList<>();
        for (SapPurchaseOrderItem sapPurchaseOrderItem:sapPurchaseOrderItemList){
            SapPurchaseOrderItem newSapPurchaseOrderItem=new SapPurchaseOrderItem();
            ClassHelper.copyProperties(sapPurchaseOrderItem,newSapPurchaseOrderItem);
            newSapPurchaseOrderItem.setId("");
            newSapPurchaseOrderItemList.add(newSapPurchaseOrderItem);
        }
        sapPurchaseOrderItemApplication.saveSapPurchaseOrderItems(newSapPurchaseOrder.getId(),newSapPurchaseOrderItemList);

        return newSapPurchaseOrder.getId();
    }
}
