package com.hzs.scm.trans.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.CacheConstants;
import com.hzs.common.core.constant.SaOrderFieldConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
import com.hzs.common.core.constant.msg.DocumentMsgConstants;
import com.hzs.common.core.constant.msg.ScmMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.scm.pub.ScmItemSpecs;
import com.hzs.common.domain.scm.pub.ScmOrderApproveLog;
import com.hzs.common.domain.scm.trans.TransferOrder;
import com.hzs.common.domain.scm.trans.TransferOrderItems;
import com.hzs.common.domain.scm.trans.ext.IcTransInBExt;
import com.hzs.common.domain.scm.trans.ext.IcTransOutBExt;
import com.hzs.common.domain.scm.trans.ext.TransferOrderExt;
import com.hzs.common.domain.system.sys.SysUser;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.scm.no.service.IScmBillNoService;
import com.hzs.scm.pub.component.ScmPubUtilTool;
import com.hzs.scm.pub.param.ItemSpecsParam;
import com.hzs.scm.pub.param.ScmApproveParam;
import com.hzs.scm.pub.service.IScmItemSpecsService;
import com.hzs.scm.pub.service.IScmOrderApproveLogService;
import com.hzs.scm.trans.mapper.TransferOrderMapper;
import com.hzs.scm.trans.param.TransferItemParam;
import com.hzs.scm.trans.param.TransferParam;
import com.hzs.scm.trans.service.ITransferOrderItemsService;
import com.hzs.scm.trans.service.ITransferOrderService;
import com.hzs.system.base.ICurrencyServiceApi;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.sys.IUserServiceApi;
import com.hzs.system.sys.dto.ApprovalBusinessResultDTO;
import com.hzs.system.sys.dto.LoginUser;
import org.apache.dubbo.config.annotation.DubboReference;
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.temporal.ChronoUnit;
import java.util.*;

/**
 * <p>
 * 调拨订单表头 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2023-12-04
 */
@Service
public class TransferOrderServiceImpl extends ServiceImpl<TransferOrderMapper, TransferOrder> implements ITransferOrderService {

    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @DubboReference
    private IUserServiceApi userServiceApi;

    @Autowired
    private IScmBillNoService scmBillNoService;

    @Autowired
    private ITransferOrderItemsService transferOrderItemsService;

    @Autowired
    private IScmItemSpecsService scmItemSpecsService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertSaveTransferOrderByOrderParam(TransferParam transferParam, Long pkMember) {
        saveTransferOrderByParam(transferParam, pkMember);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTransferOrderByOrderParam(TransferOrderExt transferOrderExt, TransferParam transferParam, Long pkMember) {
        // 更新规格明细表，先删除在新增 根据主表主键删除
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.TRANS_ORDER.getValue(), transferOrderExt.getPkId(), pkMember);
        transferOrderExt.setPkInCorp(transferParam.getPkInCorp());
        transferOrderExt.setTransType(transferParam.getTransType());
        transferOrderExt.setOrderDate(transferParam.getOrderDate());
        transferOrderExt.setPkCorp(transferParam.getPkCorp());
        transferOrderExt.setRemark(transferParam.getRemark());
        transferOrderExt.setPkInCountry(transferParam.getPkInCountry());
        // 更新订单明细表 分为3部分 删除的 新增的 修改的
        List<TransferOrderItems> transferOrderItemsList = getTransferOrderItems(transferParam, pkMember, transferOrderExt);
        // 重新处理订单明细，将订单明细分为 删除的、新增的、修改的
        List<TransferOrderItems> transOrderItemsExtList = transferOrderExt.getTransferOrderItemsList();
        // 剩余的就是需要删除的
        Map<Long, TransferOrderItems> transferOrderItemsMap = new HashMap<>();
        transOrderItemsExtList.forEach(transferOrderItems ->
                transferOrderItemsMap.put(transferOrderItems.getPkId(), transferOrderItems));
        List<TransferOrderItems> insertOrderItems = new ArrayList<>();
        List<TransferOrderItems> updateOrderItems = new ArrayList<>();
        List<ScmItemSpecs> saveScmItemSpecsList = new ArrayList<>();
        for (TransferOrderItems transferOrderItems : transferOrderItemsList) {
            if (transferOrderItems.getPkId() != null && transferOrderItemsMap.containsKey(transferOrderItems.getPkId())) {
                // 修改的
                transferOrderItems.setPkCreator(transferOrderItemsMap.get(transferOrderItems.getPkId()).getPkCreator());
                updateOrderItems.add(transferOrderItems);
                saveScmItemSpecsList.addAll(transferOrderItems.getScmItemSpecsList());
                transferOrderItemsMap.remove(transferOrderItems.getPkId());
            } else {
                // 新增的
                transferOrderItems.setPkTransfer(transferOrderExt.getPkId());
                insertOrderItems.add(transferOrderItems);
            }
        }
        String purchaseLockKey = CacheConstants.TRANSFER_ORDER_LOCK + transferOrderExt.getPkId();
        try {
            if (!redisService.lockKeyOnce(purchaseLockKey)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            if (insertOrderItems.size() > 0) {
                // 保存订单明细 新增的
                transferOrderItemsService.saveBatch(insertOrderItems);
                List<ScmItemSpecs> scmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(insertOrderItems, transferOrderExt.getPkId());
                if (scmItemSpecsList.size() > 0) {
                    saveScmItemSpecsList.addAll(scmItemSpecsList);
                }
            }
            if (updateOrderItems.size() > 0) {
                // 修改订单明细 修改的
                updateOrderItems.forEach(updateItems ->
                        transferOrderItemsService.updateById(updateItems));

            }
            if (transferOrderItemsMap.size() > 0) {
                // 删除订单明细 删除的
                List<TransferOrderItems> delOrderItems = new ArrayList<>();
                transferOrderItemsMap.forEach((key, value) -> delOrderItems.add(value));
                transferOrderItemsService.deleteTransferOrderItemsService(delOrderItems, pkMember);
            }
            // 保存订单明细规格
            if (saveScmItemSpecsList.size() > 0) {
                scmItemSpecsService.saveBatch(saveScmItemSpecsList);
            }
            // 更新订单表
            updateById(transferOrderExt);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            redisService.unlock(purchaseLockKey);
        }
    }

    @Override
    public TransferOrderExt queryTransferOrderById(Long pkOrder, Integer orderStatus) {
        return baseMapper.queryTransferOrderById(pkOrder, orderStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TransferOrderExt queryDisTransferOrderById(Long pkOrder, Integer orderStatus) {
        TransferParam transferParam = new TransferParam();
        transferParam.setPkId(pkOrder);
        transferParam.setOrderStatus(orderStatus);
        List<TransferOrderExt> transferOrderExtList = baseMapper.queryTransferOrderByCondition(transferParam);
        if (CollectionUtil.isNotEmpty(transferOrderExtList)) {
            return transferOrderExtList.get(0);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TransferOrderExt> queryTransferOrderByCondition(TransferParam transferParam) {
        if (transferParam.getEndDate() != null) {
            transferParam.setEndDate(DateUtils.afterDate(1, ChronoUnit.DAYS, transferParam.getEndDate()));
        }
        return baseMapper.queryTransferOrderByCondition(transferParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTransferOrder(Long pkTransfer, Long pkMember) {
        String transferOrderLock = CacheConstants.TRANSFER_ORDER_LOCK + pkTransfer;
        try {
            if (!redisService.lockKeyOnce(transferOrderLock)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            // 删除规格明细表
            scmItemSpecsService.deleteItemSpecsById(EScmOrderType.TRANS_ORDER.getValue(), pkTransfer, pkMember);
            // 删除订单明细表
            transferOrderItemsService.deleteTransferOrderItemsByPkOrder(pkTransfer, pkMember);
            // 删除订单主表
            UpdateWrapper<TransferOrder> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set(SystemFieldConstants.DEL_FLAG, EYesNo.NO.getIntValue());
            updateWrapper.set(SystemFieldConstants.PK_MODIFIED, pkMember);
            updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, DateUtils.currentDateTime());
            updateWrapper.eq(SystemFieldConstants.PK_ID, pkTransfer);
            update(updateWrapper);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            redisService.unlock(transferOrderLock);
        }
    }

    @Override
    public List<TransferOrderExt> queryTransferOrderByOrderItems(List<TransferItemParam> orderItemsParamList) {
        return baseMapper.queryTransferOrderByOrderItems(orderItemsParamList);
    }

    @Override
    public List<TransferOrderExt> queryTransferOrderToStoreByCondition(TransferParam transferParam) {
        return baseMapper.queryTransferOrderToStoreByCondition(transferParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTransferOrderItemsTotalInNum(List<IcTransInBExt> transferInbList, Long pkMember) {
        transferOrderItemsService.updateTransferOrderItemsTotalInNum(transferInbList, pkMember);
        baseMapper.updateTransferOrderStatusByTrans(transferInbList, pkMember, EScmOrderStatus.DELIVERY.getValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTransferOrderItemsTotalOutNum(List<IcTransOutBExt> transferOutbList, Long pkMember) {
        transferOrderItemsService.updateTransferOrderItemsTotalOutNum(transferOutbList, pkMember);
    }

    private String approveTransferOrderByStatus(ApprovalBusinessResultDTO approvalBusinessResultDTO, Integer scmOrderStatus, Integer approveStatus) {
        // 查询订单日志表
        List<ScmOrderApproveLog> scmOrderApproveLogList = scmOrderApproveLogService.queryScmOrderApproveLogByCondition(null, approvalBusinessResultDTO.getEApprovalBusiness().getValue(), approvalBusinessResultDTO.getBusinessCode());
        if (scmOrderApproveLogList == null || scmOrderApproveLogList.size() == 0) {
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_NOT_EXISTS);
        }
        ScmOrderApproveLog scmOrderApproveLog = scmOrderApproveLogList.get(0);
        // 查询采购订单
        TransferOrderExt transferOrderExt = queryTransferOrderById(scmOrderApproveLog.getPkOrder(), EScmOrderStatus.SUBMIT.getValue());
        if (transferOrderExt == null) {
            log.error("订单撤单同意处理失败: 签呈已处理!");
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_HAS_HANDLE);
        }
        // 更新采购入库单状态
        updateTransferOrderStatus(transferOrderExt.getPkId(), approvalBusinessResultDTO.getLoginUser(), scmOrderStatus);
        // 更新前程日志表状态
        scmOrderApproveLogService.updateScmOrderApproveStatus(scmOrderApproveLog.getPkId(), approvalBusinessResultDTO.getLoginUser().getUserId(), approveStatus);
        return null;
    }

    /*
     * @description: 将采购订单的参数转换为能保存的订单
     * @author: sui q
     * @date: 2023/11/20 15:53
     * @param: null null
     **/
    private void saveTransferOrderByParam(TransferParam transferParam, Long pkMember) {
        TransferOrder transferOrder = BeanUtil.copyProperties(transferParam, TransferOrder.class);
        List<TransferOrderItems> transferOrderItemsList = getTransferOrderItems(transferParam, pkMember, transferOrder);
        // 生成单据号
        transferOrder.setOrderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.TRANS_ORDER.getValue()));
        // 保存主表
        save(transferOrder);
        for (TransferOrderItems transferOrderItems : transferOrderItemsList) {
            transferOrderItems.setPkTransfer(transferOrder.getPkId());
        }
        // 保存子表
        transferOrderItemsService.saveBatch(transferOrderItemsList);
        List<ScmItemSpecs> saveScmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(transferOrderItemsList, transferOrder.getPkId());
        if (saveScmItemSpecsList.size() > 0) {
            scmItemSpecsService.saveBatch(saveScmItemSpecsList);
        }
    }

    private List<TransferOrderItems> getTransferOrderItems(TransferParam transferParam, Long pkMember, TransferOrder transferOrder) {
        // 根据国家获得汇率
        CurrencyDTO currencyDTO = currencyServiceApi.getCurrency(transferParam.getPkCountry()).getData();
        transferOrder.setPkRate(currencyDTO.getPkId());
        SysUser sysUser = userServiceApi.selectUserById(pkMember).getData();
        // 根据登录账号获得部门
        transferOrder.setPkDept(sysUser.getPkDept().intValue());
        transferOrder.setPkWhsmanager(pkMember);
        // 计算累计数量 累计价税合计
        // 总数量
        BigDecimal totalNum = BigDecimal.ZERO;
        // 价税合计
        BigDecimal totalOrigmny = BigDecimal.ZERO;
        List<TransferOrderItems> transferOrderItemsList = new ArrayList<>();
        Date date = DateUtils.currentDateTime();
        for (TransferItemParam transferItemParam : transferParam.getTransferItemParamList()) {
            TransferOrderItems transferOrderItems = BeanUtil.copyProperties(transferItemParam, TransferOrderItems.class);
            // 含税单价  = 无税单价*（1+税率）
            transferOrderItems.setNorigtaxprice(ComputeUtil.computeMultiply(transferOrderItems.getNorigprice(),
                    ComputeUtil.computeAdd(BigDecimal.ONE, ComputeUtil.computeMultiply(transferOrderItems.getNtaxrate(), BigDecimal.valueOf(0.01)))));
            // 无税金额  = 无税单价*数量
            transferOrderItems.setNorigmny(ComputeUtil.computeMultiply(transferOrderItems.getNorigprice(), transferOrderItems.getNnum()));
            // 税额 =无税单价*税率*数量
            transferOrderItems.setNtax(ComputeUtil.computeMultiply(ComputeUtil.computeBonusMultiply(transferOrderItems.getNorigprice(), transferOrderItems.getNtaxrate()), transferOrderItems.getNnum()));
            // 价税合计 含税单价*数量
            transferOrderItems.setNorigtaxmny(ComputeUtil.computeMultiply(transferOrderItems.getNorigtaxprice(), transferOrderItems.getNnum()));
            transferOrderItems.setPkRate(currencyDTO.getPkId());
            totalNum = ComputeUtil.computeAdd(totalNum, transferOrderItems.getNnum());
            totalOrigmny = ComputeUtil.computeAdd(totalOrigmny, transferOrderItems.getNorigtaxmny());
            List<ItemSpecsParam> itemSpecsParamList = transferItemParam.getScmItemSpecsList();
            scmItemSpecsService.packageScmItemByParam(itemSpecsParamList, transferOrderItems, transferParam.getPkCountry(), pkMember,
                    transferOrder.getPkId(), transferOrderItems.getPkId(), EScmOrderType.TRANS_ORDER.getValue());
            transferOrderItemsList.add(transferOrderItems);
        }
        transferOrder.setPkCountry(transferParam.getPkCountry());
        if (transferOrder.getPkId() == null) {
            transferOrder.setPkCreator(pkMember);
        } else {
            transferOrder.setPkModified(pkMember);
            transferOrder.setModifiedTime(date);
        }
        transferOrder.setTotalNum(totalNum);
        transferOrder.setTotalOrigmny(totalOrigmny);
        return transferOrderItemsList;
    }

    private void updateTransferOrderStatus(Long pkId, LoginUser loginUser, Integer orderStatus) {
        UpdateWrapper<TransferOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(SaOrderFieldConstants.ORDER_STATUS, orderStatus);
        updateWrapper.set(SystemFieldConstants.PK_MODIFIED, loginUser.getUserId());
        updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, DateUtils.currentDateTime());
        updateWrapper.eq(SystemFieldConstants.PK_ID, pkId);
        update(updateWrapper);
    }
}
