package com.fjhx.service.purchase.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
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.Assert;
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_60.getKey())
                                .eq(ApplyPurchase::getPurchaseId, id)
                                .update();
                    }

                    /**
                     * 驳回
                     *
                     */
                    @Transactional(rollbackFor = {Exception.class})
                    @Override
                    public void reject() {
                        Long id = getCacheData(Long.class);
                        // 修改采购状态
                        purchaseService.lambdaUpdate()
                                .set(Purchase::getStatus, PurchaseStatusEnum.STATUS_20.getKey())
                                .eq(Purchase::getId, id)
                                .update();

                        // 修改申购状态为已驳回
                        applyPurchaseService.lambdaUpdate()
                                .set(ApplyPurchase::getStatus, ApplyPurchaseStatusEnum.STATUS_50.getKey())
                                .eq(ApplyPurchase::getPurchaseId, id)
                                .update();
                    }

                }
        );
    }

    /**
     * 发起
     *
     * @param purchase
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void start(Purchase purchase) {
        List<ApplyPurchase> goodsList = purchase.getGoodsList();
        Assert.notEmpty(goodsList, "采购物品不能为空");

        Long supplierId = purchase.getSupplierId();
        Assert.notEmpty(supplierId, "供应商id不能为空");

        if (!redisLockClient.lockFair(REDIS_LOCK_CACHE_KEY, () -> {
            if (Func.isEmpty(purchase.getId())) {
                purchase.setId(IdWorker.getId());
            }

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

            purchase.setStatus(PurchaseStatusEnum.STATUS_10.getKey());
            // 采购金额
            BigDecimal price = new BigDecimal(BigDecimal.ZERO.intValue());

            for (ApplyPurchase goods : goodsList) {
                goods.setPurchaseId(purchase.getId());
                goods.setPurchaseCode(purchase.getCode());
                goods.setStatus(ApplyPurchaseStatusEnum.STATUS_40.getKey());
                price = price.add(BigDecimalUtil.multiply(goods.getQuantity(), goods.getUnitPrice(), 2));
            }
            purchase.setPrice(price);
            purchaseService.saveOrUpdate(purchase);
            applyPurchaseService.saveOrUpdateBatch(goodsList);

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

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

            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());
    }
}
