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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.ep.order.application.EpSaleOrderCancelApplication;
import com.huigou.topsun.ep.order.application.EpSaleOrderCancelItemApplication;
import com.huigou.topsun.ep.order.application.EpSaleOrderItemApplication;
import com.huigou.topsun.ep.order.domain.EpSaleOrder;
import com.huigou.topsun.ep.order.domain.EpSaleOrderCancel;
import com.huigou.topsun.ep.order.domain.EpSaleOrderCancelItem;
import com.huigou.topsun.ep.order.domain.EpSaleOrderItem;
import com.huigou.topsun.ep.order.domain.query.EpSaleOrderCancelQueryRequest;
import com.huigou.topsun.ep.order.domain.vo.EpSaleOrderCancelItemVo;
import com.huigou.topsun.ep.order.domain.vo.EpSaleOrderCancelVo;
import com.huigou.topsun.ep.order.domain.vo.EpSaleOrderItemVo;
import com.huigou.topsun.ep.order.repository.EpSaleOrderCancelRepository;
import com.huigou.topsun.sap.common.HttpClient;
import com.huigou.topsun.sap.common.application.SapMutualEpLogApplication;
import com.huigou.topsun.sap.common.domain.EpResult;
import com.huigou.topsun.sap.costReimbursement.domain.SapCostReimbursement;
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.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("epSaleOrderCancelApplication")
public class EpSaleOrderCancelApplicationImpl extends FlowBroker implements EpSaleOrderCancelApplication {
    @Autowired
    private EpSaleOrderCancelRepository epSaleOrderCancelRepository;
    @Autowired
    private EpSaleOrderCancelItemApplication epSaleOrderCancelItemApplication;
    @Autowired
    private HttpClient httpClient;
    @Resource
    private WorkflowApplication workflowApplication;
    @Resource
    private OperatorApplication operatorApplication;
    @Autowired
    SapMutualEpLogApplication sapMutualEpLogApplication;

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        EpSaleOrderCancel epSaleOrderCancel = getBizEntity(EpSaleOrderCancel.class);
        if (epSaleOrderCancel.isNew()) {
            epSaleOrderCancel.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            epSaleOrderCancel = (EpSaleOrderCancel) commonDomainService.loadAndFillinProperties(epSaleOrderCancel);
        }
        epSaleOrderCancel = epSaleOrderCancelRepository.save(epSaleOrderCancel);
        List<EpSaleOrderCancelItem> epSaleOrderCancelItems = getBizEntities(EpSaleOrderCancelItem.class, "items");
        epSaleOrderCancelItemApplication.saveEpSaleOrderCancelItems(epSaleOrderCancel.getId(),epSaleOrderCancelItems);
        return epSaleOrderCancel.getId();
    }
    
    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        return ClassHelper.toMap(epSaleOrderCancelRepository.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(EpSaleOrderCancel.class, bizId, status.getId());
    }

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

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        EpSaleOrderCancel epSaleOrderCancel = epSaleOrderCancelRepository.findOne(bizId);
        epSaleOrderCancel.setStatusId(BizBillStatus.ABORTED.getId());
        epSaleOrderCancelRepository.save(epSaleOrderCancel);

        this.feedBackSaleOrderCancel(epSaleOrderCancel,"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();
            EpSaleOrderCancel epSaleOrderCancel = epSaleOrderCancelRepository.findOne(bizId);
            epSaleOrderCancel.setStatusId(BizBillStatus.APPLYING.getId());
            epSaleOrderCancelRepository.save(epSaleOrderCancel);
            this.feedBackSaleOrderCancel(epSaleOrderCancel,"0");
            //回退后终止流程
//            DelegateExecution execution = delegateTask.getExecution();
//            this.onAbortProcessInstance(execution);
            //this.feedBackSaleOrderCancel(epSaleOrderCancel,"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) {
        EpSaleOrderCancel saleOrderCancel = this.epSaleOrderCancelRepository.findOne(bizId);
        String vbeln = this.getBizAndApprovalData().getString("vbeln");
        if (StringUtil.isBlank(vbeln)){
            List<EpSaleOrderCancelItem> itemList = epSaleOrderCancelItemApplication.findByEpSaleOrderCancelId(bizId);
            Set<String> vbelns = itemList.stream().map(EpSaleOrderCancelItem::getVbeln).collect(Collectors.toSet());
            vbeln = String.join(",", vbelns);
        }
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", saleOrderCancel.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", saleOrderCancel.getCustomerName(), vbeln, fillinDateStr);
    }
    
    
    @Override
    public EpSaleOrderCancel findEpSaleOrderCancelById(String id) {
        return epSaleOrderCancelRepository.findOne(id);
    }

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

    @Override
    public void updateEpSaleOrderCancel(EpSaleOrderCancel epSaleOrderCancel) {
        epSaleOrderCancelRepository.save(epSaleOrderCancel);
    }

    @Override
    public EpSaleOrderCancel saveEpSaleOrderCancel(EpSaleOrderCancel epSaleOrderCancel) {
        return epSaleOrderCancelRepository.save(epSaleOrderCancel);
    }

    @Override
    public Map<String, Object> slicedEpSaleOrderCancelList(EpSaleOrderCancelQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "epSaleOrderCancel");
        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 saveEpSaleOrderCancelVo(List<EpSaleOrderCancelVo> epSaleOrderCancelVos) {
        for (EpSaleOrderCancelVo epSaleOrderCancelVo : epSaleOrderCancelVos) {
            EpSaleOrderCancel epSaleOrderCancel = new EpSaleOrderCancel();
            BeanUtil.copyProperties(epSaleOrderCancelVo,epSaleOrderCancel);

            //初始化用户信息
            String personCode = epSaleOrderCancelVos.get(0).getPersonCode();
            QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery("config/topsun/ep/epSaleOrder/epSaleOrder.xml", "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);
            epSaleOrderCancel.setDefaultValues(new OrgUnit(operator.getFullId(), operator.getFullName()));
            SDO localSdo = new SDO();
            localSdo.setOperator(operator);
            Map<String, Object> formData = BeanUtil.beanToMap(epSaleOrderCancel);
            List<EpSaleOrderCancelItemVo> epSaleOrderCancelItemVos = epSaleOrderCancelVo.getEpSaleOrderCancelItemVos();
            Set<String> vbelns = epSaleOrderCancelItemVos.stream().map(EpSaleOrderCancelItemVo::getVbeln).collect(Collectors.toSet());
            String vbeln = String.join(",", vbelns);
            formData.put("vbeln",vbeln);
            String bizId = this.startProcessInstance(EpSaleOrderCancelApplication.PROCESS_DEFINITION_KEY, formData, localSdo);
            epSaleOrderCancel.setId(bizId);
            epSaleOrderCancel.setStatusId(BizBillStatus.APPLYING.getId());  //LXH 改为申请状态
            epSaleOrderCancel = epSaleOrderCancelRepository.save(epSaleOrderCancel);
            BeanUtil.copyProperties(epSaleOrderCancelVo, epSaleOrderCancel);



                List<EpSaleOrderCancelItem> epSaleOrderCancelItems = new ArrayList<>();
                epSaleOrderCancelItemVos.forEach(epSaleOrderCancelItemVo -> {
                    EpSaleOrderCancelItem epSaleOrderCancelItem = new EpSaleOrderCancelItem();
                    BeanUtil.copyProperties(epSaleOrderCancelItemVo, epSaleOrderCancelItem);
                    epSaleOrderCancelItems.add(epSaleOrderCancelItem);
                });
                this.epSaleOrderCancelItemApplication.saveEpSaleOrderCancelItems(epSaleOrderCancel.getId(), epSaleOrderCancelItems);

        }
        }

    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 feedBackSaleOrderCancel(EpSaleOrderCancel epSaleOrderCancel,String state){
        List<EpSaleOrderCancelItem> orderItemList = epSaleOrderCancelItemApplication.findByEpSaleOrderCancelId(epSaleOrderCancel.getId());
        Map<String,Object> map = new HashMap<>();
        map.put("state",state);
        Set<String> saleOrderNos = new HashSet<>();
        for (EpSaleOrderCancelItem epSaleOrderCancelItem : orderItemList) {
            saleOrderNos.add(epSaleOrderCancelItem.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());
            }
            epSaleOrderCancel.setCode(epResult.getCode());
            epSaleOrderCancel.setMsg(epResult.getMsg());
            epSaleOrderCancelRepository.save(epSaleOrderCancel);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            resultMap.put("businessType", epSaleOrderCancel.getOrderTypeName());
            resultMap.put("businessId", epSaleOrderCancel.getId());
            resultMap.put("parameter", JSON.toJSONString(map));
            resultMap.put("sequence", resultMap.get("row"));
            sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
        }
    }
}
