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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.math.MathUtil;
import com.alibaba.fastjson.JSONObject;
import com.huigou.cache.DictUtil;
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.sap.common.HttpClient;
import com.huigou.topsun.sap.common.domain.SapResult;
import com.huigou.topsun.sap.costReimbursement.domain.SapCostReimbursement;
import com.huigou.topsun.sap.permit.application.SapPermitApplication;
import com.huigou.topsun.sap.permit.vo.SapPermitItemVo;
import com.huigou.topsun.sap.permit.vo.SapPermitVo;
import com.huigou.topsun.sap.purchase.domain.SapPurchase;
import com.huigou.topsun.sap.wasteSale.domain.WasteSale;
import com.huigou.topsun.sap.wasteSale.domain.WasteSaleItem;
import com.huigou.topsun.sap.wasteSale.application.WasteSaleApplication;
import com.huigou.topsun.sap.wasteSale.application.WasteSaleItemApplication;
import com.huigou.topsun.sap.wasteSale.domain.query.WasteSaleQueryRequest;
import com.huigou.topsun.sap.wasteSale.domain.vo.SapWasteSaleItemVo;
import com.huigou.topsun.sap.wasteSale.domain.vo.SapWasteSaleVo;
import com.huigou.topsun.sap.wasteSale.repository.WasteSaleRepository;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.util.ClassHelper;
import com.huigou.util.DateUtil;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
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;

/**
 * @Auther: xin.lu
 * @Date: 2024/03/13/19:14
 * @Description:
 */
@Service("wasteSaleApplication")
public class WasteSaleApplicationImpl extends FlowBroker implements WasteSaleApplication {
    @Autowired
    private WasteSaleRepository wasteSaleRepository;
    @Autowired
    private WasteSaleItemApplication wasteSaleItemApplication;
    @Autowired
    private HttpClient httpClient;
    @Autowired
    private SapPermitApplication sapPermitApplication;
    @Autowired
    private TaskExecutor asyncWriteExecutor;
    @Override
    public WasteSale findWasteSaleById(String id) {
        return wasteSaleRepository.findOne(id);
    }

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

    @Override
    public WasteSale saveWasteSale(WasteSale wasteSale) {
        return wasteSaleRepository.save(wasteSale);
    }

    @Override
    public Map<String, Object> slicedWasteSaleList(WasteSaleQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "wasteSale");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status", DictUtil.getDictionary("bizBillStatus"));
        queryModel.addCriteria(" order by bill_code desc ");
        Map<String, Object> map = this.sqlExecutorDao.executeSlicedQuery(queryModel);
        return map;
    }

    @Override
    public void sendWasteSaleData(WasteSale wasteSale) {
        List<WasteSaleItem> saleItemList = wasteSaleItemApplication.findByWasteSaleId(wasteSale.getId());
        List<SapWasteSaleItemVo> sapWasteSaleVoList = new ArrayList<>();
        SapWasteSaleVo sapWasteSaleVo = new SapWasteSaleVo();
        sapWasteSaleVo.setBurks(wasteSale.getBurks());
        sapWasteSaleVo.setBlart("SA");
        String dateFormat = DateUtil.getDateFormat(wasteSale.getBudat(), "yyyyMMdd");
        sapWasteSaleVo.setBudat(dateFormat);
        sapWasteSaleVo.setBldat(DateUtil.getDateFormat(new Date(), "yyyyMMdd"));
        sapWasteSaleVo.setGjahr(dateFormat.substring(0,4));
        sapWasteSaleVo.setMonat(dateFormat.substring(4,6));
        sapWasteSaleVo.setWaers("CNY");
        sapWasteSaleVo.setBktxt(wasteSale.getBktxt()+"-"+wasteSale.getTotalMoney());
        sapWasteSaleVo.setXblnr(wasteSale.getBillCode());
        Integer  i = 1;
        for (WasteSaleItem wasteSaleItem : saleItemList) {
            SapWasteSaleItemVo sapWasteSaleItemVo = new SapWasteSaleItemVo();
            sapWasteSaleItemVo.setShkzg("S");
            sapWasteSaleItemVo.setKoart("S");
            sapWasteSaleItemVo.setBschl("40");
            sapWasteSaleItemVo.setKtonr(wasteSale.getPaymentMethod());
            sapWasteSaleItemVo.setWrbtr(wasteSaleItem.getAmount().toString());
            sapWasteSaleItemVo.setSgtxt("废品回收-"+wasteSaleItem.getWasteType()+"-"+wasteSaleItem.getQuantity()+wasteSaleItem.getUnit()+"-"+wasteSaleItem.getAmount());
            sapWasteSaleItemVo.setRstgr("113");
            sapWasteSaleItemVo.setBuzei(i.toString());
            sapWasteSaleVoList.add(sapWasteSaleItemVo);
            i++;
            SapWasteSaleItemVo sapWasteSaleItemNextVo = new SapWasteSaleItemVo();
            BeanUtil.copyProperties(sapWasteSaleItemVo,sapWasteSaleItemNextVo);
            sapWasteSaleItemNextVo.setBuzei(i.toString());
            sapWasteSaleItemNextVo.setShkzg("H");
            sapWasteSaleItemNextVo.setBschl("50");
            sapWasteSaleItemNextVo.setKtonr("6301090000");
            sapWasteSaleItemNextVo.setRstgr("");
            //计算不含税总价  “单项总价”/1+税率
            BigDecimal decimal = wasteSaleItem.getAmount().divide(wasteSaleItem.getKbetr().add(BigDecimal.ONE),2,BigDecimal.ROUND_HALF_UP);
            sapWasteSaleItemNextVo.setWrbtr(decimal.toString());
            sapWasteSaleVoList.add(sapWasteSaleItemNextVo);
            i++;
            SapWasteSaleItemVo sapWasteSaleItemThirdVo = new SapWasteSaleItemVo();
            BeanUtil.copyProperties(sapWasteSaleItemVo,sapWasteSaleItemThirdVo);
            sapWasteSaleItemThirdVo.setBuzei(i.toString());
            sapWasteSaleItemThirdVo.setShkzg("H");
            sapWasteSaleItemThirdVo.setBschl("50");
            sapWasteSaleItemThirdVo.setKtonr("2221010400");
            sapWasteSaleItemThirdVo.setRstgr("");
            //税费=含税-不含税
            BigDecimal subtract = wasteSaleItem.getAmount().subtract(decimal);
            sapWasteSaleItemThirdVo.setWrbtr(subtract.toString());
            sapWasteSaleVoList.add(sapWasteSaleItemThirdVo);
            i++;
        }
        sapWasteSaleVo.setWasteSaleItemVos(sapWasteSaleVoList);
        try {
            //String url = SystemCache.getParameter("sap.purchase.url", String.class);
            String execute = httpClient.execute(sapWasteSaleVo, "cud_scrap_sale/scrap_sale");
            List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
            SapResult sapResult = resultList.get(0);
            if (!"S".equals(sapResult.getTYPE())){
                throw new RuntimeException("数据传输失败，"+ sapResult.getMESSAGE());
            }
            wasteSale.setType(sapResult.getTYPE());
            wasteSale.setMessageV1(sapResult.getMESSAGE_V2().substring(0,10));
            wasteSaleRepository.save(wasteSale);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        asyncWriteExecutor.execute(()->
            //创建放行条
            this.startSapPermit(wasteSale,saleItemList)
        );
    }

    public void startSapPermit(WasteSale wasteSale,List<WasteSaleItem> saleItemList){
        SapPermitVo sapPermitVo = new SapPermitVo();
        sapPermitVo.setCompany(wasteSale.getBktxt());
        sapPermitVo.setApplyPerson(wasteSale.getPersonMemberId());
        sapPermitVo.setApplyPersonName(wasteSale.getPersonMemberName());
        sapPermitVo.setDutyDepart(wasteSale.getDeptId());
        sapPermitVo.setDutyDepartName(wasteSale.getDeptName());
        sapPermitVo.setPermitDate(new Date());
        List<SapPermitItemVo> sapPermitItemVos = new ArrayList<>();
        for (WasteSaleItem wasteSaleItem : saleItemList) {
            SapPermitItemVo sapPermitItemVo = new SapPermitItemVo();
            sapPermitItemVo.setBelongings(wasteSaleItem.getSaleGoods());
            sapPermitItemVo.setUnit(wasteSaleItem.getUnit());

           String remark="车辆皮重:"+wasteSaleItem.getCarWeight()+" 毛重:"+wasteSaleItem.getGrossWeight()+" 扣减重量:"+wasteSaleItem.getDeductWeight();//+"净重:"+wasteSaleItem.getNetWeight();
            sapPermitItemVo.setRemark(remark);
            sapPermitItemVo.setQuantity(wasteSaleItem.getQuantity());
            sapPermitItemVo.setUnit(wasteSaleItem.getUnit());
            sapPermitItemVo.setUnitName(wasteSaleItem.getUnitName());
            sapPermitItemVos.add(sapPermitItemVo);
        }
        sapPermitVo.setItemVos(sapPermitItemVos);
        //创建放行条
        sapPermitApplication.saveSapPermitVo(sapPermitVo);
    }

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        WasteSale wasteSale = getBizEntity(WasteSale.class);
        if (wasteSale.isNew()) {
            wasteSale.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            wasteSale = (WasteSale) commonDomainService.loadAndFillinProperties(wasteSale);
        }
        wasteSale = wasteSaleRepository.save(wasteSale);
        List<WasteSaleItem> wasteSaleItems = getBizEntities(WasteSaleItem.class, "items");
        wasteSaleItemApplication.saveWasteSaleItems(wasteSale.getId(),wasteSaleItems);
        return wasteSale.getId();
    }

    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        return ClassHelper.toMap(wasteSaleRepository.getOne(bizId));
    }

    /**
     * 任务完成前执行
     */
    @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);
        }
    }

    @Transactional
    protected void updateStatus(String bizId, BizBillStatus status) {
        Assert.hasText(bizId, CommonDomainConstants.ID_NOT_BLANK);
        this.commonDomainService.updateStatus(WasteSale.class, bizId, status.getId());
    }

    /**
     * 流程撤销事件
     **/
    @Override
    protected void onRecallProcessInstance(DelegateExecution delegateExecution) {
        String bizId = delegateExecution.getProcessBusinessKey();
        // 修改单据状态为申请
        updateStatus(bizId, BizBillStatus.APPLYING);
    }

    /**
     * 回收事件
     **/
    @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);
        }
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        WasteSale wasteSale = wasteSaleRepository.findOne(bizId);
        wasteSale.setStatusId(status.getId());
        wasteSaleRepository.save(wasteSale);
        if (status == BizBillStatus.COMPLETED){
            this.sendWasteSaleData(wasteSale);
        }
    }

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

    /**
     * @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();
            WasteSale wasteSale = wasteSaleRepository.findOne(bizId);
            wasteSale.setStatusId(BizBillStatus.APPLYING.getId());
            wasteSaleRepository.save(wasteSale);
        }
    }
    /**
     * 设置任务名称
     */
    @Override
    protected void setTaskDescription(DelegateTask delegateTask) {
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        delegateTask.setDescription(this.getApprovalSubjectName(bizId));
    }

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        WasteSale wasteSale = this.wasteSaleRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", wasteSale.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", "废品销售单", wasteSale.getBillCode(), fillinDateStr);
    }
}
