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

import cn.hutool.core.bean.BeanUtil;
import com.huigou.cache.DictUtil;
import com.huigou.context.Operator;
import com.huigou.context.OrgUnit;
import com.huigou.context.ThreadLocalUtil;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.data.query.model.QueryModel;
import com.huigou.topsun.sap.clientMaterials.application.ClientMaterialsApplication;
import com.huigou.topsun.sap.clientMaterials.application.ClientMaterialsApplication;

import com.huigou.topsun.sap.clientMaterials.application.ClientMaterialsItemApplication;
import com.huigou.topsun.sap.clientMaterials.domain.ClientMaterials;

import com.huigou.topsun.sap.clientMaterials.domain.ClientMaterialsItem;
import com.huigou.topsun.sap.clientMaterials.domain.query.ClientMaterialsQueryRequest;

import com.huigou.topsun.sap.clientMaterials.repository.ClientMaterialsItemRepository;
import com.huigou.topsun.sap.clientMaterials.repository.ClientMaterialsRepository;

import com.huigou.topsun.sap.clientMaterials.vo.ClientMaterialsVo;
import com.huigou.topsun.sap.componentSupply.domain.ComponentSupplyItem;
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.ClassHelper;
import com.huigou.util.Constants;
import com.huigou.util.JSONUtil;
import com.huigou.util.SDO;
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.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: Lxh
 * @Date: 2024/06/05/11:35
 * @Description:
 */
@Service("clientMaterialsApplication")
public class ClientMaterialsApplicationImpl extends FlowBroker implements ClientMaterialsApplication {
    @Autowired
    private ClientMaterialsRepository clientMaterialsRepository;

    @Autowired
    private ClientMaterialsItemRepository clientMaterialsItemRepository;

    @Autowired
    private ClientMaterialsItemApplication clientMaterialsItemApplication;
    @Autowired
    private WorkflowApplication workflowApplication;
    @Autowired
    private OperatorApplication operatorApplication;


    @Override
    public Map<String, Object> getClientMaterialsList(ClientMaterialsQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "clientMaterials");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        if (queryRequest.getStatus() != null) {
            queryModel.addCriteria(" and t.status =:status");
            queryModel.putParam("status", queryRequest.getStatus());
        }
        if (queryRequest.getBillCode() != null) {
            queryModel.addCriteria(" and t.bill_code like:billCode");
            queryModel.putLikeParam("billCode", queryRequest.getBillCode());
        }
        if (queryRequest.getRemark() != null) {
            queryModel.addCriteria(" and t.remark like:remark");
            queryModel.putLikeParam("remark", queryRequest.getRemark());
        }
        if (queryRequest.getUsed() != null) {
            queryModel.addCriteria(" and t.used =:used");
            queryModel.putParam("used", queryRequest.getUsed());
        }
        queryModel.putDictionary("status", DictUtil.getDictionary("bizBillStatus"));
        queryModel.putDictionary("used", DictUtil.getDictionary("materialUse"));
        queryModel.addCriteria(" order by bill_code desc ");
        Map<String, Object> map = this.sqlExecutorDao.executeSlicedQuery(queryModel);
        return map;
    }

    @Override
    public ClientMaterials getClientMaterialsById(String id) {
        return clientMaterialsRepository.findOne(id);
    }

    @Override
    public void deleteByIds(List<String> ids) {
        ids.forEach(id->{
             clientMaterialsRepository.delete(id);
            List<ClientMaterialsItem> list=clientMaterialsItemRepository.findByClientMaterialsId(id);
            for (ClientMaterialsItem clientMaterialsItem:list){
                clientMaterialsItemRepository.delete(clientMaterialsItem);
            }
        });
    }

    @Override
    protected void onBeforeComplete(DelegateTask delegateTask) {
        super.onBeforeComplete(delegateTask);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        if (this.isApplyProcUnit(delegateTask) && this.getApprovalParameter().isAdvanceProcessAction()) {
            ClientMaterials clientMaterials = clientMaterialsRepository.findOne(bizId);
            clientMaterials.setStatusId(BizBillStatus.APPROVING.getId());
            clientMaterialsRepository.save(clientMaterials);
        }
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        ClientMaterials clientMaterials = clientMaterialsRepository.findOne(bizId);
        clientMaterials.setStatusId(status.getId());
        clientMaterialsRepository.save(clientMaterials);
    }

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

    @Override
    protected void onBack(DelegateTask delegateTask, String destActivityId) {
        super.onBack(delegateTask, destActivityId);
        if ("Apply".equalsIgnoreCase(destActivityId)) {
            String bizId = delegateTask.getExecution().getProcessBusinessKey();
            ClientMaterials clientMaterials = clientMaterialsRepository.findOne(bizId);
            clientMaterials.setStatusId(BizBillStatus.APPLYING.getId());
            clientMaterialsRepository.save(clientMaterials);
        }
    }

    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        return ClassHelper.toMap(clientMaterialsRepository.getOne(bizId));
    }

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        ClientMaterials clientMaterials = getBizEntity(ClientMaterials.class);
        if (clientMaterials.isNew()) {
            clientMaterials.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            clientMaterials = (ClientMaterials) commonDomainService.loadAndFillinProperties(clientMaterials);
        }
        clientMaterials = clientMaterialsRepository.save(clientMaterials);
        List<ClientMaterialsItem> items = getBizEntities(ClientMaterialsItem.class, "items");
        if (items.size()<1){
            throw new IllegalArgumentException("没有客户供料通知明细信息!");
        }
        clientMaterialsItemApplication.saveClientMaterialsItems(clientMaterials.getId(),items);
//        List<ClientMaterialsItem> items = getBizEntities(ClientMaterialsItem.class, "items");
//        if (items.size()<1){
//           throw new IllegalArgumentException("没有补充发料明细信息!");
//        }
     //   ClientMaterialsItemApplication.saveClientMaterialsItems(ClientMaterials.getId(),items);
        //更新附件ID为主键ID
//        if (!(ClientMaterials.getId().equals(ClientMaterials.getAttbizId()))) {
//            List<Attachment> attachmentList = attachmentApplication.queryAttachments("sapRetirementInfo", ClientMaterials.getAttbizId());
//            for (Attachment attachment : attachmentList) {
//                attachment.setBizId(ClientMaterials.getId());
//                attachmentApplication.saveAttachment(attachment);
//            }
//        }
        return clientMaterials.getId();
    }

    @Override
    public void saveClientMaterialsVo(ClientMaterialsVo clientMaterialsVo){
        ClientMaterials clientMaterials = new ClientMaterials();
        BeanUtil.copyProperties(clientMaterialsVo,clientMaterials);
        //初始化用户信息
        Operator operator = operatorApplication.createOperatorByPersonMemberId(clientMaterialsVo.getApplyPerson());
        clientMaterials.setDefaultValues(new OrgUnit(operator.getFullId(), operator.getFullName()));

        Map<String, Object> formData = BeanUtil.beanToMap(clientMaterials);
        //保存明细
//        List<ClientMaterialsItemVo> itemVos = ClientMaterialsVo.getItemVos();
//        List<ClientMaterialsItem> ClientMaterialsItems = new ArrayList<>();
//        if (!CollectionUtils.isEmpty(itemVos)){
//            ClientMaterialsItems= itemVos
//                    .stream()
//                    .map(itemVo -> {
//                        ClientMaterialsItem ClientMaterialsItem = new ClientMaterialsItem();
//                        BeanUtil.copyProperties(itemVo, ClientMaterialsItem);
//                        return ClientMaterialsItem;
//                    }).collect(Collectors.toList());
//        formData.put("items", JSONUtil.toString(ClientMaterialsItems));
        //启动流程实例
        this.startProcessInstance(ClientMaterialsApplication.PROCESS_DEFINITION_KEY, formData);
        //ClientMaterials.setId(bizId);
        //this.ClientMaterialsRepository.save(ClientMaterials);
        //}
    }

    public String startProcessInstance(String processDefinitionKey,Map<String, Object> formData){
        Map<String, Object> variables = new HashMap();
        SDO localSdo = this.buildSDO(formData);
        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;
    }

    private SDO buildSDO(Map<String, Object> formData) {
        String createdById = (String) formData.get("applyPerson");
        Operator operator = operatorApplication.createOperatorByPersonMemberId(createdById);
        SDO localSdo = new SDO();
        // 将业务数据传递给工作流
        formData.forEach(localSdo::putProperty);
        // 将业务流程信息传递给工作流
        localSdo.putProperty("processAction", ProcessAction.SAVE);
        localSdo.putProperty("procUnitId", "Apply");
        localSdo.setOperator(operator);
        return localSdo;
    }


}
