package com.huigou.topsun.ep.order.application.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.ep.order.application.EpSaleOrderApplication;
import com.huigou.topsun.ep.order.domain.EpSaleOrderItem;
import com.huigou.topsun.ep.order.domain.vo.EpSaleOrderItemVo;
import com.huigou.topsun.ep.order.domain.vo.EpSaleOrderVo;
import com.huigou.topsun.ep.order.repository.EpSaleOrderRepository;
import com.huigou.topsun.sap.common.HttpClient;
import com.huigou.topsun.ep.order.application.EpSaleOrderItemApplication;
import com.huigou.topsun.ep.order.domain.EpSaleOrder;
import com.huigou.topsun.ep.order.domain.query.EpSaleOrderQueryRequest;
import com.huigou.topsun.sap.common.application.SapMutualEpLogApplication;
import com.huigou.topsun.sap.common.domain.EpResult;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.operator.OperatorApplication;
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.runtime.ProcessInstance;
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.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: xin.lu
 * @Date: 2024/03/12/19:17
 * @Description:
 */
@Service("epSaleOrderApplication")
public class EpSaleOrderApplicationImpl extends FlowBroker implements EpSaleOrderApplication {
    @Autowired
    private EpSaleOrderRepository epSaleOrderRepository;
    @Autowired
    private EpSaleOrderItemApplication epSaleOrderItemApplication;
    @Autowired
    private HttpClient httpClient;
    @Resource
    private WorkflowApplication workflowApplication;
    @Resource
    private OperatorApplication operatorApplication;
    @Autowired
    SapMutualEpLogApplication sapMutualEpLogApplication;
    @Autowired
    private MannualStartWorkApplication mannualStartWorkApplication;
    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        EpSaleOrder epSaleOrder = getBizEntity(EpSaleOrder.class);
        if (epSaleOrder.isNew()) {
            epSaleOrder.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            epSaleOrder = (EpSaleOrder) commonDomainService.loadAndFillinProperties(epSaleOrder);
        }
        epSaleOrder = epSaleOrderRepository.save(epSaleOrder);
        List<EpSaleOrderItem> epSaleOrderItems = getBizEntities(EpSaleOrderItem.class, "epSaleOrderItems");
        epSaleOrderItemApplication.saveEpSaleOrderItems(epSaleOrder.getId(),epSaleOrderItems);
        return epSaleOrder.getId();
    }
    
    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        return ClassHelper.toMap(epSaleOrderRepository.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(EpSaleOrder.class, bizId, status.getId());
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        //super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        EpSaleOrder epSaleOrder = epSaleOrderRepository.findOne(bizId);
        epSaleOrder.setStatusId(status.getId());
        epSaleOrderRepository.save(epSaleOrder);
        this.feedBackSaleOrder(epSaleOrder,"1");
    }

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        EpSaleOrder epSaleOrder = epSaleOrderRepository.findOne(bizId);
        epSaleOrder.setStatusId(BizBillStatus.ABORTED.getId());
        epSaleOrderRepository.save(epSaleOrder);

        this.feedBackSaleOrder(epSaleOrder,"5");
    }

    /**
     * @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();
            EpSaleOrder epSaleOrder = epSaleOrderRepository.findOne(bizId);
            epSaleOrder.setStatusId(BizBillStatus.APPLYING.getId());
            epSaleOrderRepository.save(epSaleOrder);
            this.feedBackSaleOrder(epSaleOrder,"0");
            //回退后终止流程
//            DelegateExecution execution = delegateTask.getExecution();
//            this.onAbortProcessInstance(execution);
//            this.feedBackSaleOrder(epSaleOrder,"0");
        }
    }

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

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        EpSaleOrder epSaleOrder = this.epSaleOrderRepository.findOne(bizId);
        String vbeln = this.getBizAndApprovalData().getString("vbeln");
        if (StringUtil.isBlank(vbeln)){
            List<EpSaleOrderItem> itemList = epSaleOrderItemApplication.findByEpSaleOrderId(bizId);
            Set<String> vbelns = itemList.stream().map(EpSaleOrderItem::getVbeln).collect(Collectors.toSet());
            vbeln = String.join(",", vbelns);
        }
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", epSaleOrder.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", epSaleOrder.getKunnr(), vbeln, fillinDateStr);
    }
    
    
    @Override
    public EpSaleOrder findEpSaleOrderById(String id) {
        return epSaleOrderRepository.findOne(id);
    }

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

    @Override
    public void updateEpSaleOrder(EpSaleOrder epSaleOrder) {
        epSaleOrderRepository.save(epSaleOrder);
    }

    @Override
    public EpSaleOrder saveEpSaleOrder(EpSaleOrder epSaleOrder) {
        return epSaleOrderRepository.save(epSaleOrder);
    }

    @Override
    public Map<String, Object> slicedEpSaleOrderList(EpSaleOrderQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "epSaleOrder");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status",BizBillStatus.getMap());
        queryModel.addCriteria(" order by bill_code desc ");
        Map<String, Object> map = this.sqlExecutorDao.executeSlicedQuery(queryModel);
        return map;
    }

    @Override
    public void saveEpSaleOrderVo(List<EpSaleOrderVo> epSaleOrderVos) {
        for (EpSaleOrderVo epSaleOrderVo : epSaleOrderVos) {
            EpSaleOrder epSaleOrder = new EpSaleOrder();
            BeanUtil.copyProperties(epSaleOrderVo,epSaleOrder);

            //初始化用户信息
            String personCode = epSaleOrderVos.get(0).getPersonCode();
            QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "loadPersonMemberId");
            String personMemberId = this.sqlExecutorDao.queryToString(queryDescriptor.getSql(), personCode);
            if (StringUtil.isBlank(personMemberId)){
                throw new RuntimeException("未找到编码为：" + personCode + " 的人员");
            }
            //String createdById =  SystemCache.getParameter("adminPersonId", String.class);
            Operator operator = operatorApplication.createOperatorByPersonMemberId(personMemberId);
            SDO localSdo = new SDO();
            localSdo.setOperator(operator);
            epSaleOrder.setDefaultValues(new OrgUnit(operator.getFullId(), operator.getFullName()));

            Map<String, Object> formData = BeanUtil.beanToMap(epSaleOrder);
            List<EpSaleOrderItemVo> epSaleOrderItemVos = epSaleOrderVo.getEpSaleOrderItemVos();
            Set<String> vbelns = epSaleOrderItemVos.stream().map(EpSaleOrderItemVo::getVbeln).collect(Collectors.toSet());
            String vbeln = String.join(",", vbelns);
            formData.put("vbeln",vbeln);
          //  String bizId = this.startProcessInstance(EpSaleOrderApplication.PROCESS_DEFINITION_KEY, formData, localSdo);
            String bizId =mannualStartWorkApplication.startWorkflow(epSaleOrder,PROCESS_DEFINITION_KEY,"epSaleOrder");

            epSaleOrder.setId(bizId);
            epSaleOrder.setStatusId(BizBillStatus.APPROVING.getId()); //lxh  08.01
          //  epSaleOrder.setStatusId(BizBillStatus.APPLYING.getId());
            epSaleOrder = epSaleOrderRepository.save(epSaleOrder);

            List<EpSaleOrderItem> epSaleOrderItems = new ArrayList<>();
            epSaleOrderItemVos.forEach(epSaleOrderItemVo -> {
                EpSaleOrderItem epSaleOrderItem = new EpSaleOrderItem();
                BeanUtil.copyProperties(epSaleOrderItemVo,epSaleOrderItem);
                epSaleOrderItems.add(epSaleOrderItem);
            });
            this.epSaleOrderItemApplication.saveEpSaleOrderItems(epSaleOrder.getId(),epSaleOrderItems);
            }
        }

    public String startProcessInstance(String processDefinitionKey,Map<String, Object> formData, SDO localSdo){
        Map<String, Object> variables = new HashMap();
        // 将业务数据传递给工作流
        formData.forEach(localSdo::putProperty);
        // 将业务流程信息传递给工作流
        localSdo.putProperty("processAction", ProcessAction.SAVE);
        localSdo.putProperty("procUnitId", "Apply");
        ThreadLocalUtil.putVariable(Constants.SDO, localSdo);
        variables.put("startModel", ProcessStartModel.MANUAL.getId());
        Operator operator = localSdo.getOperator();
        variables.put("executorFullId", operator.getFullId());
        variables.put("executorFullName", operator.getFullName());
        ThreadLocalUtil.putOperator(operator);
        ThreadLocalUtil.putVariable("client.ip", "127.0.0.1");
        ProcessInstance processInstance = this.workflowApplication.startProcessInstanceByKey(processDefinitionKey, variables);
        String businessKey = processInstance.getBusinessKey();
        return businessKey;
    }

    public void feedBackSaleOrder(EpSaleOrder epSaleOrder,String state){
        List<EpSaleOrderItem> orderItemList = epSaleOrderItemApplication.findByEpSaleOrderId(epSaleOrder.getId());
        Map<String,Object> map = new HashMap<>();
        map.put("state",state);
        Set<String> saleOrderNos = new HashSet<>();
        for (EpSaleOrderItem epSaleOrderItem : orderItemList) {
            saleOrderNos.add(epSaleOrderItem.getVbeln());
        }
        map.put("saleOrderNos",saleOrderNos);
        //日志记录
        Map<String, Object> resultMap = new HashMap<>();
        try {
            String execute = httpClient.executeForEp(map, "od/saleOrder/auditedResult");
            EpResult epResult = JSONObject.parseObject(execute, EpResult.class);
            resultMap.put("TYPE", epResult.getCode());
            resultMap.put("message", epResult.getMsg());
            if (!"200".equals(epResult.getCode())){
                throw new RuntimeException("数据传输失败，"+ epResult.getMsg());
            }
            epSaleOrder.setCode(epResult.getCode());
            epSaleOrder.setMsg(epResult.getMsg());
            epSaleOrderRepository.save(epSaleOrder);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            resultMap.put("businessType", epSaleOrder.getOrderTypeName());
            resultMap.put("businessId", epSaleOrder.getId());
            resultMap.put("parameter", JSON.toJSONString(map));
            resultMap.put("sequence", resultMap.get("row"));
            sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
        }
    }
}
