package com.fjhx.service.purchase.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fjhx.constants.common.CommonConstant;
import com.fjhx.entity.apply.ApplyPurchase;
import com.fjhx.entity.purchase.Purchase;
import com.fjhx.enums.apply.ApplyPurchaseStatusEnum;
import com.fjhx.enums.flow.FlowCodeEnum;
import com.fjhx.enums.purchase.PurchaseStatusEnum;
import com.fjhx.feign.IFlowClient;
import com.fjhx.params.ExampleResult;
import com.fjhx.service.apply.ApplyPurchaseService;
import com.fjhx.service.purchase.PurchaseFlowService;
import com.fjhx.service.purchase.PurchaseService;
import com.fjhx.uitl.code.CodeEnum;
import com.fjhx.uitl.flow.FlowUserUtil;
import com.fjhx.utils.BigDecimalUtil;
import com.fjhx.utils.ExampleAbstract;
import com.fjhx.utils.FlowConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.lock.RedisLockClient;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

/**
 * <p>
 * 采购：流程 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-12-01
 */
@Service
public class PurchaseFlowServiceImpl implements PurchaseFlowService {

    @Autowired
    private PurchaseService purchaseService;

    @Autowired
    private ApplyPurchaseService applyPurchaseService;

    @Autowired
    private RedisLockClient redisLockClient;

    @Autowired
    private IFlowClient iFlowClient;

    private final String REDIS_LOCK_CACHE_KEY = "seq:lock:" + AuthUtil.getTenantId() + ":purchase:";

    /**
     * 初始化流程
     *
     * @return
     */
    private FlowConstructor flowConstructor() {
        return FlowConstructor.init(
                new ExampleAbstract() {
                    @Override
                    public String getCode() {
                        return FlowCodeEnum.PURCHASE.getValue();
                    }

                    /**
                     * 结束
                     *
                     */
                    @Transactional(rollbackFor = {Exception.class})
                    @Override
                    public void end() {
                        Long id = getCacheData(Long.class);
                        //修改采购状态
                        purchaseService.lambdaUpdate().set(Purchase::getStatus, PurchaseStatusEnum.STATUS_30.getKey()).eq(Purchase::getId, id).update();
                        //修改申购状态
                        applyPurchaseService.lambdaUpdate().set(ApplyPurchase::getStatus, ApplyPurchaseStatusEnum.STATUS_30.getKey()).eq(ApplyPurchase::getPurchaseId, id).update();
                    }

                    /**
                     * 驳回
                     *
                     */
                    @Transactional(rollbackFor = {Exception.class})
                    @Override
                    public void reject() {
                        Purchase purchase = purchaseService.getById(getCacheData(Long.class));
                        flowConstructor().deleteLogic(purchase.getFlowId());
                    }

                    /**
                     * 删除流程
                     *
                     * @return
                     */
                    @Transactional(rollbackFor = {Exception.class})
                    @Override
                    public boolean deleteLogic() {
                        Long id = getCacheData(Long.class);
                        //修改采购状态
                        purchaseService.lambdaUpdate().set(Purchase::getStatus, PurchaseStatusEnum.STATUS_20.getKey()).set(Purchase::getDelFlag, CommonConstant.YesOrNo.YES).eq(Purchase::getId, id).update();
                        //修改申购状态
                        applyPurchaseService.lambdaUpdate()
                                .set(ApplyPurchase::getStatus, ApplyPurchaseStatusEnum.STATUS_10.getKey())
                                .set(ApplyPurchase::getUnitPrice, null)
                                .set(ApplyPurchase::getPurchaseId, null)
                                .set(ApplyPurchase::getPurchaseCode, null)
                                .eq(ApplyPurchase::getPurchaseId, id)
                                .update();
                        return true;
                    }
                }
        );
    }

    /**
     * 发起
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void start(Purchase entity) {
        if (!redisLockClient.lockFair(REDIS_LOCK_CACHE_KEY, () -> {
            if (Func.isEmpty(entity.getId())) {
                entity.setId(IdWorker.getId());
            }

            if (Func.isBlank(entity.getCode())) {
                //获取编码
                entity.setCode(CodeEnum.APPLY_PURCHASE.getCode());
                //查询编码是否已存在
                if (!checkCodeIsExist(null, entity.getCode())) {
                    throw new ServiceException("后台自增编码存在重复，请重试或联系管理员！编码：" + entity.getCode());
                }
            }

            //流程标题
            String title = AuthUtil.getUserName() + " 在" + LocalDate.now() + "日发起了 采购审批流程（单号：" + entity.getCode() + "）";

            ExampleResult exampleResult = null;
            if (Func.isEmpty(entity.getFlowId())) {
                //启动流程
                exampleResult = flowConstructor().create(entity.getId(), title, entity.getFlowRemark(), entity.getId());
            } else {
                //获取当前节点对应的按钮ID
                Long buttonId = iFlowClient.getButtonIdByExampleInfoId(entity.getFlowId());
                //审批操作（用于驳回后重新提交）
                exampleResult = flowConstructor().jump(entity.getId(), buttonId, entity.getFlowRemark(), entity.getId());
            }

            //事务回滚
            ExampleResult finalExampleResult = exampleResult;
            exampleResult.after(() -> {
                //处理下一节点处理人信息
                JSONObject nextNodeHandleUserInfo = new JSONObject();
                FlowUserUtil.getNextNodeHandleUserInfo(finalExampleResult, nextNodeHandleUserInfo);
                entity.setFlowId(nextNodeHandleUserInfo.getLong("flowId"));
                entity.setFlowApproverId(nextNodeHandleUserInfo.getLong("flowApproverId"));
                entity.setFlowApproverName(nextNodeHandleUserInfo.getString("flowApproverName"));
                entity.setStatus(PurchaseStatusEnum.STATUS_10.getKey());
                //采购金额
                BigDecimal price = new BigDecimal(BigDecimal.ZERO.intValue());

                for (ApplyPurchase goods : entity.getGoodsList()) {
                    goods.setPurchaseId(entity.getId());
                    goods.setPurchaseCode(entity.getCode());
                    goods.setStatus(ApplyPurchaseStatusEnum.STATUS_20.getKey());
                    price = price.add(BigDecimalUtil.multiply(goods.getQuantity(), goods.getUnitPrice(), 2));
                }
                entity.setPrice(price);
                purchaseService.saveOrUpdate(entity);

                applyPurchaseService.saveOrUpdateBatch(entity.getGoodsList());
            });
            return true;
        })) {
            throw new ServiceException("当前系统繁忙，请稍后重试！");
        }
    }

    /**
     * 审批
     *
     * @param entity
     * @return
     */
    @Override
    public void examine(Purchase entity) {
        Purchase purchase = purchaseService.getById(entity.getId());
        if (Func.isEmpty(purchase)) {
            throw new ServiceException("操作异常，业务数据不存在！");
        }

        //审批操作
        ExampleResult exampleResult = flowConstructor().jump(entity.getId(), entity.getButtonId(), entity.getFlowRemark(), entity.getId());
        exampleResult.after(() -> {
            //处理下一节点处理人信息
            JSONObject nextNodeHandleUserInfo = new JSONObject();
            FlowUserUtil.getNextNodeHandleUserInfo(exampleResult, nextNodeHandleUserInfo);
            entity.setFlowId(nextNodeHandleUserInfo.getLong("flowId"));
            entity.setFlowApproverId(nextNodeHandleUserInfo.getLong("flowApproverId"));
            entity.setFlowApproverName(nextNodeHandleUserInfo.getString("flowApproverName"));

            //修改流程信息
            purchaseService.updateById(entity);
        });
    }

    private Boolean checkCodeIsExist(Long id, String code) {
        List<Purchase> list = purchaseService.lambdaQuery().ne(Func.isNotEmpty(id), Purchase::getId, id).eq(Purchase::getCode, code).list();
        return !Func.isNotEmpty(list);
    }

    /**
     * 详情
     *
     * @param entity
     * @return
     */
    @Override
    public Purchase details(Purchase entity) {
        return purchaseService.getFlowDetailsById(entity.getId());
    }
}
