package com.fjhx.sale.flow;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fjhx.common.entity.AvailableStockBo;
import com.fjhx.common.enums.FlowStatusEnum1;
import com.fjhx.common.utils.Assert;
import com.fjhx.common.utils.Utils;
import com.fjhx.flow.core.FlowDelegate;
import com.fjhx.flow.enums.FlowStatusEnum;
import com.fjhx.item.enums.ProductAvailableRecordType;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.purchase.entity.purchase.enums.PurchaseStatusEnum;
import com.fjhx.sale.entity.purchase.dto.EhsdPurchaseDto;
import com.fjhx.sale.entity.purchase.po.EhsdPurchase;
import com.fjhx.sale.entity.purchase.po.EhsdPurchaseProduct;
import com.fjhx.sale.entity.purchase.po.EhsdPurchaseProject;
import com.fjhx.sale.service.purchase.EhsdPurchaseProductService;
import com.fjhx.sale.service.purchase.EhsdPurchaseProjectService;
import com.fjhx.sale.service.purchase.EhsdPurchaseService;
import com.fjhx.wms.entity.stock.po.StockWaitDetails;
import com.fjhx.wms.service.stock.StockWaitDetailsService;
import com.fjhx.wms.service.stock.StockWaitService;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 采购变更流程
 */
@Component
public class EhsdPurchaseUpdateFlow extends FlowDelegate {
    @Autowired
    private EhsdPurchaseService ehsdPurchaseService;
    @Autowired
    private EhsdPurchaseFlow ehsdPurchaseFlow;
    @Autowired
    private EhsdPurchaseProductService ehsdPurchaseProductService;
    @Autowired
    private EhsdPurchaseProjectService ehsdPurchaseProjectService;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private StockWaitDetailsService stockWaitDetailsService;
    @Autowired
    private StockWaitService stockWaitService;

    @Override
    public String getFlowKey() {
        return "purchase_update_flow";
    }

    /**
     * 发起流程
     */
    @Override
    public Long start(Long flowId, JSONObject submitData) {
        EhsdPurchaseDto purchase = submitData.toJavaObject(EhsdPurchaseDto.class);
        Assert.notEmpty(purchase.getId(), "原采购订单id不能为空");
        //赋值原采购id 并 清空id
        purchase.setOldPurchaseId(purchase.getId());
        purchase.setId(null);

        //赋值流程id
        purchase.setFlowId(flowId);

        //获取原采购id
        Long oldPurchaseId = purchase.getOldPurchaseId();

        //判断合同是否在变更中，防止用户缓存导致重复变更
        EhsdPurchase oldPurchase = ehsdPurchaseService.getById(oldPurchaseId);
        Assert.notEmpty(oldPurchase, "查询不到原采购订单信息");
        if (oldPurchase.getStatus().equals(FlowStatusEnum1.UPDATE_LOADING.getKey())) {
            throw new ServiceException("原采购订单正在变更中，禁止重复变更！");
        }

        //原采购订单修改为变更中
        ehsdPurchaseService.update(q -> q.eq(EhsdPurchase::getId, oldPurchaseId).set(EhsdPurchase::getStatus, FlowStatusEnum1.UPDATE_LOADING.getKey()));

        //赋值新单号
        purchase.setCode(Utils.getNewCode(oldPurchase.getCode()));

        //获取明细信息
        List<EhsdPurchaseProduct> purchaseProductList = purchase.getPurchaseProductList();
        List<EhsdPurchaseProject> purchaseProjectList = purchase.getPurchaseProjectList();
        //赋值原id 清除id字段
        for (EhsdPurchaseProduct ehsdPurchaseProduct : purchaseProductList) {
            ehsdPurchaseProduct.setOldPurchaseProductId(ehsdPurchaseProduct.getId());
            ehsdPurchaseProduct.setId(null);
        }
        purchaseProjectList.forEach(item -> item.setId(null));

        //调用采购发起公共代码块
        purchase = ehsdPurchaseFlow.connStart(purchase);

        //回传单号给流程引擎
        submitData.put("code", purchase.getCode());
        submitData.put("currency", purchase.getCurrency());

        return purchase.getId();
    }

    /**
     * 结束流程
     */
    @Override
    public void end(Long flowId, Long businessId, JSONObject submitData) {
        //通过业务ID查询采购数据
        EhsdPurchase purchase = ehsdPurchaseService.getById(businessId);
        Assert.notEmpty(purchase, "采购单不存在,或已被删除");

        //修改采购状态为审批通过
        purchase.setStatus(PurchaseStatusEnum.PASS.getKey());
        purchase.setApprovedDate(new Date());
        ehsdPurchaseService.updateById(purchase);

        //原合同改为 已变更
        EhsdPurchase oldEhsdPurchase = ehsdPurchaseService.getById(purchase.getOldPurchaseId());
        oldEhsdPurchase.setStatus(FlowStatusEnum1.UPDATE.getKey());
        ehsdPurchaseService.updateById(oldEhsdPurchase);


        //---------------------------------------------
        //获取新采购明细数据
        Map<Long, BigDecimal> newQuantityMap = ehsdPurchaseProductService.mapKV(
                EhsdPurchaseProduct::getOldPurchaseProductId, EhsdPurchaseProduct::getQuantity,
                q -> q.eq(EhsdPurchaseProduct::getPurchaseId, businessId)
        );

        List<EhsdPurchaseProduct> oldPurchaseProductList = ehsdPurchaseProductService.list(q -> q.eq(EhsdPurchaseProduct::getPurchaseId, purchase.getOldPurchaseId()));

        List<AvailableStockBo> availableStockBoList = new ArrayList<>();

        //旧数据处理
        Long stockWaitId = null;
        for (EhsdPurchaseProduct oldPurchaseProduct : oldPurchaseProductList) {
            //新数量
            BigDecimal newQuantity = newQuantityMap.get(oldPurchaseProduct.getId());
            //已入库数量
            StockWaitDetails stockWaitDetails = stockWaitDetailsService.getOne(q -> q.eq(StockWaitDetails::getBusinessDetailsId, oldPurchaseProduct.getId()));
            stockWaitId = stockWaitDetails.getStockWaitId();

            //生成操作可用库存的实体
            AvailableStockBo availableStockBo = new AvailableStockBo();
            availableStockBo.setProductId(oldPurchaseProduct.getProductId());
            availableStockBo.setQuantity(oldPurchaseProduct.getQuantity());
            availableStockBo.setNewQuantity(newQuantity);
            availableStockBo.setInStockQuantity(stockWaitDetails.getReceiptQuantity());

            availableStockBoList.add(availableStockBo);


            //操作待入库数据
            if (ObjectUtils.isEmpty(newQuantity)) {
                //原数据被删，检查已入库数量，>0禁止变更
                stockWaitDetailsService.removeById(stockWaitDetails);
            } else {
                stockWaitDetails.setQuantity(newQuantity);
                //计算状态
                int status = stockWaitDetails.getReceiptQuantity().compareTo(stockWaitDetails.getQuantity()) >= 0 ? 2 : 1;
                if (stockWaitDetails.getReceiptQuantity().compareTo(BigDecimal.ZERO) == 0) {
                    status = 0;
                }
                stockWaitDetails.setStatus(status);
                stockWaitDetailsService.updateById(stockWaitDetails);

                stockWaitService.updateStatus(stockWaitDetails.getStockWaitId());
            }
        }

        //新添加的数据处理
        List<EhsdPurchaseProduct> newPurchaseProductInfo = ehsdPurchaseProductService.list(q -> q
                .eq(EhsdPurchaseProduct::getPurchaseId, businessId)
                .isNull(EhsdPurchaseProduct::getOldPurchaseProductId)
        );
        for (EhsdPurchaseProduct newPurchaseProduct : newPurchaseProductInfo) {
            //生成操作可用库存的实体
            AvailableStockBo availableStockBo = new AvailableStockBo();
            availableStockBo.setProductId(newPurchaseProduct.getProductId());
            availableStockBo.setQuantity(null);
            availableStockBo.setNewQuantity(newPurchaseProduct.getQuantity());
            availableStockBo.setInStockQuantity(null);
            availableStockBoList.add(availableStockBo);

            //生成待入库
            Assert.notEmpty(stockWaitId, "查询不到待入库信息！");
            StockWaitDetails stockWaitDetails = new StockWaitDetails();
            stockWaitDetails.setStockWaitId(stockWaitId);
            stockWaitDetails.setBusinessDetailsId(newPurchaseProduct.getId());
            stockWaitDetails.setPurchaseDetailId(newPurchaseProduct.getId());

            stockWaitDetails.setProductId(newPurchaseProduct.getProductId());
            stockWaitDetails.setQuantity(newPurchaseProduct.getQuantity());
            stockWaitDetails.setStatus(0);
            stockWaitDetailsService.save(stockWaitDetails);

            stockWaitService.updateStatus(stockWaitDetails.getStockWaitId());
        }


        //修改可用库存
        productInfoService.editAvailableQuantity(availableStockBoList, businessId, ProductAvailableRecordType.PURCHASE_UPDATE, purchase.getCompanyId());

//----------------------------------------------------------------------------

        Long oldPurchaseId = purchase.getOldPurchaseId();

        //先将当前合同id 以及 当前合同关联数据的合同id 改为临时id
        long tempId = IdWorker.getId();
        ehsdPurchaseService.updatePurchaseId(businessId, tempId, SecurityUtils.getUserId(), null);
        ehsdPurchaseProductService.update(q -> q.eq(EhsdPurchaseProduct::getPurchaseId, businessId).set(EhsdPurchaseProduct::getPurchaseId, tempId));
        ehsdPurchaseProjectService.update(q -> q.eq(EhsdPurchaseProject::getPurchaseId, businessId).set(EhsdPurchaseProject::getPurchaseId, tempId));


        //将旧合同的id改为新合同id
        ehsdPurchaseService.updatePurchaseId(oldPurchaseId, businessId, SecurityUtils.getUserId(), null);
        ehsdPurchaseProductService.update(q -> q
                .eq(EhsdPurchaseProduct::getPurchaseId, oldPurchaseId)
                .set(EhsdPurchaseProduct::getPurchaseId, businessId)
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
        ehsdPurchaseProjectService.update(q -> q
                .eq(EhsdPurchaseProject::getPurchaseId, oldPurchaseId)
                .set(EhsdPurchaseProject::getPurchaseId, businessId)
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
        //将新合同id改为旧合同id
        ehsdPurchaseService.updatePurchaseId(tempId, oldPurchaseId, SecurityUtils.getUserId(), businessId);
        ehsdPurchaseProductService.update(q -> q
                .eq(EhsdPurchaseProduct::getPurchaseId, tempId)
                .set(EhsdPurchaseProduct::getPurchaseId, oldPurchaseId)
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
        ehsdPurchaseProjectService.update(q -> q
                .eq(EhsdPurchaseProject::getPurchaseId, tempId)
                .set(EhsdPurchaseProject::getPurchaseId, oldPurchaseId)
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }

    /**
     * 重新发起
     */
    @Override
    public void relaunch(Long flowId, Long businessId, FlowStatusEnum flowStatus, JSONObject submitData) {
        EhsdPurchaseDto purchase = submitData.toJavaObject(EhsdPurchaseDto.class);
        if (ObjectUtils.isEmpty(purchase)) {
            throw new ServiceException("采购数据不能为空");
        }
        purchase.setFlowId(flowId);
        ehsdPurchaseFlow.connStart(purchase);
    }

    /**
     * 驳回
     */
    @Override
    public void reject(Long flowId, Long businessId, FlowStatusEnum flowStatus) {
        ehsdPurchaseService.update(q -> q
                .eq(EhsdPurchase::getId, businessId)
                .set(EhsdPurchase::getStatus, FlowStatusEnum1.REJECT.getKey())
                .set(EhsdPurchase::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        //恢复原合同
        EhsdPurchase ehsdPurchase = ehsdPurchaseService.getById(businessId);
        ehsdPurchaseService.update(q -> q
                .eq(BasePo::getId, ehsdPurchase.getOldPurchaseId())
                .set(EhsdPurchase::getStatus, FlowStatusEnum1.PASS.getKey())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }

    /**
     * 作废
     */
    @Override
    public void cancellation(Long flowId, Long businessId, FlowStatusEnum flowStatus) {
        super.cancellation(flowId, businessId, flowStatus);
        ehsdPurchaseService.update(q -> q
                .eq(EhsdPurchase::getId, businessId)
                .set(EhsdPurchase::getStatus, FlowStatusEnum1.CANCELLATION.getKey())
                .set(EhsdPurchase::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        //恢复原合同
        EhsdPurchase ehsdPurchase = ehsdPurchaseService.getById(businessId);
        ehsdPurchaseService.update(q -> q
                .eq(BasePo::getId, ehsdPurchase.getOldPurchaseId())
                .set(EhsdPurchase::getStatus, FlowStatusEnum1.PASS.getKey())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }

}
