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.*;
import com.hzs.common.domain.scm.trans.ext.IcTransOutBExt;
import com.hzs.common.domain.scm.trans.ext.IcTransOutHExt;
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.ic.service.IIcOnHandNumService;
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.IcTransOutHMapper;
import com.hzs.scm.trans.param.TransferItemParam;
import com.hzs.scm.trans.param.TransferParam;
import com.hzs.scm.trans.service.IIcTransOutBService;
import com.hzs.scm.trans.service.IIcTransOutHService;
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.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 调拨出库单表头 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2023-12-04
 */
@Service
public class IcTransOutHServiceImpl extends ServiceImpl<IcTransOutHMapper, IcTransOutH> implements IIcTransOutHService {

    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @DubboReference
    private IUserServiceApi userServiceApi;

    @Autowired
    private IScmBillNoService scmBillNoService;

    @Autowired
    private IScmItemSpecsService scmItemSpecsService;

    @Autowired
    private IIcTransOutBService transOutBiService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;

    @Autowired
    private IIcOnHandNumService onHandNumService;

    @Autowired
    private ITransferOrderService transferOrderService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertTransferOutByTransferParam(List<TransferOrderExt> transferOrderList, TransferParam transferParam, Long pkMember) {
        saveTransferByParam(transferOrderList, transferParam, pkMember);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTransferOutByTransferParam(List<TransferOrderExt> transferOrderList, IcTransOutHExt transferOutExt, TransferParam transferParam, Long pkMember) {
        // 更新规格明细表，先删除在新增 根据主表主键删除
        transferOutExt.setOrderDate(transferParam.getOrderDate());
        transferOutExt.setRemark(transferParam.getRemark());
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.TRANS_OUT.getValue(), transferOutExt.getPkId(), pkMember);
        // 更新订单明细表 分为3部分 删除的 新增的 修改的
        List<IcTransOutB> icTransOutbList = getTransferItems(transferParam, pkMember, transferOutExt);
        // 重新处理订单明细，将订单明细分为 删除的、新增的、修改的
        List<IcTransOutBExt> transOutbExtList = transferOutExt.getTransOutbExtList();
        // 剩余的就是需要删除的
        Map<Long, IcTransOutBExt> generalOutbExtMap = transOutbExtList.stream().collect(Collectors.toMap(IcTransOutBExt::getPkId, transOutbExt-> transOutbExt));
        List<IcTransOutB> insertTransferItems = new ArrayList<>();
        List<IcTransOutB> updateTransferItems = new ArrayList<>();
        for (IcTransOutB transOutB : icTransOutbList) {
            if (transOutB.getPkId() != null && generalOutbExtMap.containsKey(transOutB.getPkId())) {
                // 修改的
                transOutB.setPkCreator(generalOutbExtMap.get(transOutB.getPkId()).getPkCreator());
                updateTransferItems.add(transOutB);
                generalOutbExtMap.remove(transOutB.getPkId());
            } else {
                // 新增的
                transOutB.setPkTransferOut(transferOutExt.getPkId());
                insertTransferItems.add(transOutB);
            }
        }
        String transOutLockKey = CacheConstants.TRANSFER_OUT_LOCK + transferOutExt.getPkId();
        try {
            if (!redisService.lockKeyOnce(transOutLockKey)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            if (insertTransferItems.size() > 0) {
                // 保存订单明细 新增的
                transOutBiService.saveBatch(insertTransferItems);
                List<ScmItemSpecs> scmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(insertTransferItems, transferOutExt.getPkId());
            }
            if (updateTransferItems.size() > 0) {
                // 修改订单明细 修改的
                updateTransferItems.forEach(updateItems ->
                        transOutBiService.updateById(updateItems));

            }
            if (generalOutbExtMap.size() > 0) {
                // 删除订单明细 删除的
                List<IcTransOutB> delTransferItems = new ArrayList<>();
                generalOutbExtMap.forEach((key, value) -> delTransferItems.add(value));
                transOutBiService.deleteTransferItemsByList(delTransferItems, pkMember);
            }
            saveScmItemSpecs(pkMember, transferOutExt, icTransOutbList, transferOrderList);
            // 更新订单表
            updateById(transferOutExt);
        } finally {
            redisService.unlock(transOutLockKey);
        }
    }

    @Override
    public IcTransOutHExt queryTransferOutById(Long pkId, Integer orderStatus) {
        return baseMapper.queryTransOutById(pkId, orderStatus);
    }

    @Override
    public IcTransOutHExt queryDisTransferOutExtById(Long pkId, Integer orderStatus) {
        TransferParam transferParam = new TransferParam();
        transferParam.setPkId(pkId);
        transferParam.setOrderStatus(orderStatus);
        List<IcTransOutHExt> transOutExtList = baseMapper.queryDisTransOutExtByCondition(transferParam);
        if(CollectionUtil.isNotEmpty(transOutExtList)){
            return transOutExtList.get(0);
        }
        return null;
    }

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

    @Override
    public List<IcTransOutHExt> queryDisTransferOutExtCondition(TransferParam transferParam) {
        if (transferParam.getEndDate() != null) {
            transferParam.setEndDate(DateUtils.afterDate(1, ChronoUnit.DAYS, transferParam.getEndDate()));
        }
        return baseMapper.queryDisTransOutExtByCondition(transferParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTransferOut(Long pkId, Long pkMember) {
        String transferOutLock = CacheConstants.TRANSFER_OUT_LOCK + pkId;
        if (!redisService.lockKeyOnce(transferOutLock)) {
            throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
        }
        // 删除规格明细表
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.TRANS_OUT.getValue(), pkId, pkMember);
        transOutBiService.deleteTransferItemsByPkTransfer(pkId, pkMember);
        UpdateWrapper<IcTransOutH> 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, pkId);
        update(updateWrapper);
        redisService.unlock(transferOutLock);
    }

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

    /*
     * @description: 将采购订单的参数转换为能保存的订单
     * @author: sui q
     * @date: 2023/11/20 15:53
     * @param: null null
     **/
    private void saveTransferByParam(List<TransferOrderExt> transferOrderList, TransferParam transferParam, Long pkMember) {
        IcTransOutH icTransferOutH = packageTransOut(transferOrderList.get(0), transferParam);
        List<IcTransOutB> transferBiList = getTransferItems(transferParam, pkMember, icTransferOutH);
        // 生成单据号
        icTransferOutH.setOrderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.TRANS_OUT.getValue()));
        // 保存主表
        save(icTransferOutH);
        for (IcTransOutB transferOutB : transferBiList) {
            transferOutB.setPkTransferOut(icTransferOutH.getPkId());
        }
        // 保存子表
        transOutBiService.saveBatch(transferBiList);
        saveScmItemSpecs(pkMember, icTransferOutH, transferBiList, transferOrderList);
    }

    /*
     * @description: 封装主表
     * @author: sui q
     * @date: 2023/12/9 12:00
     * @param: null null
     **/
    private IcTransOutH packageTransOut(TransferOrderExt transferOrderExt, TransferParam transferParam) {
        IcTransOutH icTransferOutH = BeanUtil.copyProperties(transferParam, IcTransOutH.class);
        icTransferOutH.setPkInCorp(transferOrderExt.getPkInCorp());
        icTransferOutH.setPkCorp(transferOrderExt.getPkCorp());
        icTransferOutH.setPkInCountry(transferOrderExt.getPkInCountry());
        icTransferOutH.setOrderStatus(EScmOrderStatus.SAVE.getValue());
        return icTransferOutH;
    }

    private void saveScmItemSpecs(Long pkMember, IcTransOutH icTransOutH, List<IcTransOutB> transOutBiList, List<TransferOrderExt> transferOrderList) {
        // 封装明细表对应的规格
        Map<Long, List<ScmItemSpecs>> itemSpecsMap = packageItemSpecsMap(transferOrderList);
        List<ScmItemSpecs> saveScmItemSpecsList = new ArrayList<>();
        for (IcTransOutB transOutB : transOutBiList) {
            if (itemSpecsMap.containsKey(transOutB.getPkTransferItems())) {
                List<ScmItemSpecs> itemSpecsList = itemSpecsMap.get(transOutB.getPkTransferItems());
                scmItemSpecsService.packageScmItemSpecsList(itemSpecsList, pkMember,
                        icTransOutH.getPkId(), transOutB.getPkId(), EScmOrderType.TRANS_OUT.getValue());
                saveScmItemSpecsList.addAll(itemSpecsList);
            }
        }
        // 保存订单明细规格
        if (saveScmItemSpecsList.size() == 0) {
            throw new RuntimeException(ScmMsgConstants.SOURCE_BILL_EXIST_SPECS);
        }
        scmItemSpecsService.saveBatch(saveScmItemSpecsList);
    }

    /*
     * @description: 调拨入库单对应的规格
     * @author: sui q
     * @date: 2023/11/24 11:21
     * @param: null null
     **/
    private Map<Long, List<ScmItemSpecs>> packageItemSpecsMap(List<TransferOrderExt> transferOrderList) {
        List<ScmItemSpecs> scmItemSpecsList = new ArrayList<>();
        for (TransferOrderExt transferOrder : transferOrderList) {
            for (TransferOrderItems transferOrderItems : transferOrder.getTransferOrderItemsList()) {
                ScmItemSpecs scmItemSpecs = ScmItemSpecs.builder()
                        .pkOrder(transferOrder.getPkId())
                        .pkOrderItems(transferOrderItems.getPkId())
                        .build();
                scmItemSpecsList.add(scmItemSpecs);
            }
        }
        return scmItemSpecsService.queryScmItemSpecsByCondition(EScmOrderType.TRANS_ORDER.getValue(), scmItemSpecsList);
    }

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

    private String approveTransferByStatus(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);
        // 查询采购入库
        IcTransOutHExt transOutExt = queryTransferOutById(scmOrderApproveLog.getPkOrder(), EScmOrderStatus.SUBMIT.getValue());
        if (transOutExt == null) {
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_HAS_HANDLE);
        }
        // 更新采购入库单状态
        updateTransferStatus(transOutExt.getPkId(), approvalBusinessResultDTO.getLoginUser(), scmOrderStatus);
        // 更新前程日志表状态
        scmOrderApproveLogService.updateScmOrderApproveStatus(scmOrderApproveLog.getPkId(), approvalBusinessResultDTO.getLoginUser().getUserId(), approveStatus);
        // 弃审的时候回退批次数量
        List<IcTransOutBExt> icTransferOutbExtList = transOutBiService.queryTransferOutBiByPk(EScmOrderType.TRANS_OUT.getValue(), transOutExt.getTransOutbExtList());
        if(EAgentApprovalStatus.REFUSE.getValue() == approveStatus){
            if(icTransferOutbExtList != null && icTransferOutbExtList.size() >0){
                transOutExt.setTransOutbExtList(icTransferOutbExtList);
            }
            onHandNumService.backIcOnHandNumByGeneralOut(transOutExt, transOutExt.getTransOutbExtList(), EScmOrderType.TRANS_OUT.getValue(), approvalBusinessResultDTO.getLoginUser().getUserId());
        }else{
            // 审核通过回写累计出库数量
            transferOrderService.updateTransferOrderItemsTotalOutNum(icTransferOutbExtList, approvalBusinessResultDTO.getLoginUser().getUserId());
        }
        return null;
    }

    private void updateTransferStatus(Long pkId, LoginUser loginUser, Integer orderStatus) {
        UpdateWrapper<IcTransOutH> 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);
    }
}
