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.IcTransInB;
import com.hzs.common.domain.scm.trans.IcTransInH;
import com.hzs.common.domain.scm.trans.TransferOrder;
import com.hzs.common.domain.scm.trans.TransferOrderItems;
import com.hzs.common.domain.scm.trans.ext.*;
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.IcTransInHMapper;
import com.hzs.scm.trans.param.TransferItemParam;
import com.hzs.scm.trans.param.TransferParam;
import com.hzs.scm.trans.service.IIcTransInBService;
import com.hzs.scm.trans.service.IIcTransInHService;
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.IApprovalServiceApi;
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;

/**
 * <p>
 * 调拨入库单表头 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2023-12-04
 */
@Service
public class IcTransInHServiceImpl extends ServiceImpl<IcTransInHMapper, IcTransInH> implements IIcTransInHService {

    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @DubboReference
    private IUserServiceApi userServiceApi;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IScmBillNoService scmBillNoService;

    @Autowired
    private IScmItemSpecsService scmItemSpecsService;

    @Autowired
    private IIcTransInBService transInbService;

    @Autowired
    private IIcOnHandNumService icOnHandNumService;

    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;

    @Autowired
    private ITransferOrderService transferOrderService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertSaveTransferInByTransferOrder(List<IcTransOutHExt> transOutExtList, TransferParam transferParam, Long pkMember) {
        // 根据调拨订单封装调拨入库单
        // 入库单表头
        Date date = DateUtils.currentDateTime();
        // 入库单表头
        IcTransInH icTransInH = packageTransferIn(transOutExtList.get(0), transferParam, date, pkMember);
        // 入库单表体
        List<IcTransInB> transInbList = packageTransferInB(transferParam, date, pkMember, icTransInH);
        // 保存主表
        save(icTransInH);
        // 保存明细表
        for (IcTransInB icTransInB : transInbList) {
            icTransInB.setPkTransferIn(icTransInH.getPkId());
        }
        transInbService.saveBatch(transInbList);
//        saveScmItemSpecs(pkMember, icTransInH, transInbList, transOutExtList);
        List<ScmItemSpecs> saveScmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(transInbList, icTransInH.getPkId());
        if (saveScmItemSpecsList.size() > 0) {
            scmItemSpecsService.saveBatch(saveScmItemSpecsList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSaveTransferInByPoOrder(List<IcTransOutHExt> transOutExtList, IcTransInHExt transInExt, TransferParam transferParam, Long pkMember) {
        // 更新规格明细表，先删除在新增 根据主表主键删除
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.TRANS_IN.getValue(), transferParam.getPkId(), pkMember);
        Date date = DateUtils.currentDateTime();
        // 入库单表头
        IcTransInH icTransInH = packageTransferIn(transOutExtList.get(0), transferParam, date, pkMember);
        // 入库单表体
        List<IcTransInB> transInbList = packageTransferInB(transferParam, date, pkMember, icTransInH);
        // merge 对入库单表体进行 icPurchaseInbList 修改或新增 查询出删除的、
        List<IcTransInB> insertTransInbList = new ArrayList<>();
        List<IcTransInB> updateTransInbList = new ArrayList<>();
        List<Long> updateIdList = new ArrayList<>();
        transInbList.forEach(transInB -> {
            if (transInB.getPkId() != null) {
                updateIdList.add(transInB.getPkId());
                updateTransInbList.add(transInB);
            } else {
                transInB.setPkTransferIn(transInExt.getPkId());
                insertTransInbList.add(transInB);
            }
        });
        List<IcTransInB> delTransInb = new ArrayList<>();
        for (IcTransInB icPurchaseInB : transInExt.getTransInbExtList()) {
            if (!updateIdList.contains(icPurchaseInB.getPkId())) {
                icPurchaseInB.setPkModified(pkMember);
                delTransInb.add(icPurchaseInB);
            }
        }
        List<String> transOrderKeyList = new ArrayList<>();
        String transInKey = CacheConstants.TRANSFER_IN_LOCK + transInExt.getPkId();
        try {
            // 加锁 调拨订单加锁，调拨入库单加锁，调拨订单同时只能被一个人操作
            for (IcTransOutHExt transOutExt : transOutExtList) {
                transOrderKeyList.add(CacheConstants.TRANSFER_OUT_LOCK + transOutExt.getPkId());
            }
            if (!redisService.lockKeyByList(transOrderKeyList)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            if (!redisService.lockKeyOnce(transInKey)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            // 删除明细
            if (delTransInb.size() > 0) {
                transInbService.deleteTransferInbByList(delTransInb);
            }
            if (insertTransInbList.size() > 0) {
                transInbService.saveBatch(insertTransInbList);
            }
            if (updateTransInbList.size() > 0) {
                updateTransInbList.forEach(purchaseInb ->
                        transInbService.updateById(purchaseInb));
            }
            saveScmItemSpecs(pkMember, icTransInH, transInbList, transOutExtList);
            icTransInH.setPkCreator(transInExt.getPkCreator());
            // 更新入库单表
            updateById(icTransInH);
        } finally {
            redisService.unlockByList(transOrderKeyList);
            redisService.unlock(transInKey);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTransferInByPk(Long pkTransferIn, Long pkMember) {
        String transferInLock = CacheConstants.TRANSFER_IN_LOCK + pkTransferIn;
        try {
            if (!redisService.lockKeyOnce(transferInLock)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            // 删除规格明细表
            scmItemSpecsService.deleteItemSpecsById(EScmOrderType.TRANS_IN.getValue(), pkTransferIn, pkMember);
            // 删除明细表
            transInbService.deleteTransferInbByPkPurchase(pkTransferIn, pkMember);
            // 删除主表
            UpdateWrapper<IcTransInH> 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, pkTransferIn);
            update(updateWrapper);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            redisService.unlock(transferInLock);
        }
    }

    @Override
    public IcTransInHExt queryTransferInInhExtById(Long pkId, Integer orderStatus, Integer pkCountry) {
        TransferParam transferParam = new TransferParam();
        transferParam.setPkId(pkId);
        transferParam.setOrderStatus(orderStatus);
        List<IcTransInHExt> transInExtList = baseMapper.queryDisTransInExtByCondition(transferParam);
        if (CollectionUtil.isNotEmpty(transInExtList)) {
            return transInExtList.get(0);
        }
        return null;
    }

    @Override
    public IcTransInHExt queryDisTransferInInhExtById(Long pkId, Integer orderStatus) {
        return baseMapper.queryTransInById(pkId, orderStatus);
    }

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

    private IcTransInH packageTransferIn(IcTransOutHExt transOutExt, TransferParam transferParam, Date date, Long pkMember) {
        SysUser sysUser = userServiceApi.selectUserById(pkMember).getData();
        // 根据登录账号获得部门
        IcTransInH transInH = IcTransInH.builder()
                .pkDept(sysUser.getPkDept().intValue())
                .pkWhsmanager(pkMember)
                .orderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.TRANS_IN.getValue()))
                .orderDate(transferParam.getOrderDate())
                .pkCorp(transOutExt.getPkInCorp())
                .pkOutCorp(transOutExt.getPkCorp())
                .pkOutCountry(transOutExt.getPkCountry())
                .orderStatus(EScmOrderStatus.SAVE.getValue())
                .remark(transferParam.getRemark())
                .build();
        if (transferParam.getPkId() == null) {
            transInH.setPkCreator(pkMember);
        } else {
            transInH.setPkId(transferParam.getPkId());
            transInH.setModifiedTime(date);
            transInH.setPkModified(pkMember);
        }
        transInH.setPkCountry(transferParam.getPkCountry());
        return transInH;
    }

    private List<IcTransInB> packageTransferInB(TransferParam transferParam, Date date, Long pkMember, IcTransInH icTransInH) {
        List<IcTransInB> transInbList = new ArrayList<>();
        // 根据国家获得汇率
        CurrencyDTO currencyDTO = currencyServiceApi.getCurrency(transferParam.getPkCountry()).getData();
        BigDecimal totalNum = BigDecimal.ZERO;
        for (TransferItemParam transferItemParam : transferParam.getTransferItemParamList()) {
            IcTransInB icTransInB = BeanUtil.copyProperties(transferItemParam, IcTransInB.class);
            icTransInB.setPkTransferOut(transferItemParam.getPkTransferOut());
            icTransInB.setPkTransferOutB(transferItemParam.getPkTransferOutB());
            // 无税金额  = 无税单价*数量
            icTransInB.setNorigmny(ComputeUtil.computeMultiply(transferItemParam.getNorigprice(), transferItemParam.getNnum()));
            // 含税单价  = 无税单价*（1+税率）
            icTransInB.setNorigtaxprice(ComputeUtil.computeMultiply(transferItemParam.getNorigprice(),
                    ComputeUtil.computeAdd(BigDecimal.ONE, ComputeUtil.computeMultiply(transferItemParam.getNtaxrate(), BigDecimal.valueOf(0.01)))));
            // 税额 =无税单价*税率*数量
            icTransInB.setNtax(ComputeUtil.computeMultiply(ComputeUtil.computeBonusMultiply(transferItemParam.getNorigprice(), transferItemParam.getNtaxrate()), transferItemParam.getNnum()));
            // 价税合计 含税单价*数量
            icTransInB.setNorigtaxmny(ComputeUtil.computeMultiply(icTransInB.getNorigtaxprice(), transferItemParam.getNnum()));
            icTransInB.setPkRate(currencyDTO.getPkId());
            totalNum = ComputeUtil.computeAdd(totalNum, icTransInB.getNnum());
            List<ItemSpecsParam> itemSpecsParamList = transferItemParam.getScmItemSpecsList();
            scmItemSpecsService.packageScmItemByParam(itemSpecsParamList, icTransInB, transferParam.getPkCountry(), pkMember,
                    icTransInH.getPkId(), icTransInB.getPkId(), EScmOrderType.TRANS_IN.getValue());
            if (icTransInB.getPkId() == null) {
                icTransInB.setPkCreator(pkMember);
            } else {
                icTransInB.setPkTransferIn(icTransInH.getPkId());
                icTransInB.setModifiedTime(date);
                icTransInB.setPkModified(pkMember);
            }
            icTransInB.setPkBatchCode(transferItemParam.getPkBatchCode());
            icTransInB.setPkCountry(transferParam.getPkCountry());
            transInbList.add(icTransInB);
        }
        icTransInH.setTotalNum(totalNum);
        return transInbList;
    }

    private void saveScmItemSpecs(Long pkMember, IcTransInH icTransInH, List<IcTransInB> transInbList, List<IcTransOutHExt> transOutExtList) {
        // 封装明细表对应的规格
        Map<Long, List<ScmItemSpecs>> itemSpecsMap = packageItemSpecsMap(transOutExtList);
        List<ScmItemSpecs> saveScmItemSpecsList = new ArrayList<>();
        for (IcTransInB icTransInB : transInbList) {
            if (itemSpecsMap.containsKey(icTransInB.getPkTransferOutB())) {
                List<ScmItemSpecs> itemSpecsList = itemSpecsMap.get(icTransInB.getPkTransferOutB());
                scmItemSpecsService.packageScmItemSpecsList(itemSpecsList, pkMember,
                        icTransInH.getPkId(), icTransInB.getPkId(), EScmOrderType.TRANS_IN.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<IcTransOutHExt> transOutExtList) {
        List<ScmItemSpecs> scmItemSpecsList = new ArrayList<>();
        for (IcTransOutHExt transOutExt : transOutExtList) {
            for (IcTransOutBExt transOutBiExt : transOutExt.getTransOutbExtList()) {
                ScmItemSpecs scmItemSpecs = ScmItemSpecs.builder()
                        .pkOrder(transOutExt.getPkId())
                        .pkOrderItems(transOutBiExt.getPkId())
                        .build();
                scmItemSpecsList.add(scmItemSpecs);
            }
        }
        return scmItemSpecsService.queryScmItemSpecsByCondition(EScmOrderType.TRANS_OUT.getValue(), scmItemSpecsList);
    }

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

    private String approveTransferInBytStatus(ApprovalBusinessResultDTO approvalBusinessResultDTO, Integer scmOrderStatus, Integer approveStatus) {
        try {
            // 查询订单日志表
            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);
            // 查询调拨入库单
            IcTransInHExt icTransInExt = queryTransferInInhExtById(scmOrderApproveLog.getPkOrder(), EScmOrderStatus.SUBMIT.getValue(), approvalBusinessResultDTO.getLoginUser().getDataCountry());
            if (icTransInExt == null) {
                return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_HAS_HANDLE);
            }
            // 更新调拨入库单状态
            updateTransferInStatus(icTransInExt.getPkId(), approvalBusinessResultDTO.getLoginUser(), scmOrderStatus);
            // 更新前程日志表状态
            scmOrderApproveLogService.updateScmOrderApproveStatus(scmOrderApproveLog.getPkId(), approvalBusinessResultDTO.getLoginUser().getUserId(), approveStatus);
            if (EAgentApprovalStatus.APPROVED.getValue() == approveStatus) {
                // 查询调拨入库单明细表
                List<IcTransInBExt> transferInbList = transInbService.queryTransferInbByPk(EScmOrderType.TRANS_IN.getValue(), icTransInExt.getTransInbExtList());
                if (transferInbList != null && transferInbList.size() > 0) {
                    icTransInExt.setTransInbExtList(transferInbList);
                }
                // 更新现存量
                icOnHandNumService.mergeIcOnHandNumByGeneralIn(icTransInExt, icTransInExt.getTransInbExtList(), EScmOrderType.TRANS_IN.getValue(), approvalBusinessResultDTO.getLoginUser().getUserId());
                // 更新调拨订单累计入库数量
                transferOrderService.updateTransferOrderItemsTotalInNum(icTransInExt.getTransInbExtList(), approvalBusinessResultDTO.getLoginUser().getUserId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return null;
    }
}
