package com.hzs.scm.general.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.general.IcGeneralInB;
import com.hzs.common.domain.scm.general.IcGeneralInH;
import com.hzs.common.domain.scm.general.ext.IcGeneralInBExt;
import com.hzs.common.domain.scm.general.ext.IcGeneralInHExt;
import com.hzs.common.domain.scm.pub.ScmItemSpecs;
import com.hzs.common.domain.scm.pub.ScmOrderApproveLog;
import com.hzs.common.domain.scm.purchase.ext.IcPurchaseInBExt;
import com.hzs.common.domain.system.sys.SysUser;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.scm.general.mapper.IcGeneralInHMapper;
import com.hzs.scm.general.param.GeneralBParam;
import com.hzs.scm.general.param.GeneralParam;
import com.hzs.scm.general.service.IIcGeneralInBService;
import com.hzs.scm.general.service.IIcGeneralInHService;
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.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.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 其他入库表头 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2023-11-27
 */
@Service
public class IcGeneralInHServiceImpl extends ServiceImpl<IcGeneralInHMapper, IcGeneralInH> implements IIcGeneralInHService {

    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @DubboReference
    private IUserServiceApi userServiceApi;

    @Autowired
    private IScmBillNoService scmBillNoService;

    @Autowired
    private IScmItemSpecsService scmItemSpecsService;

    @Autowired
    private IIcGeneralInBService generalInbService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;

    @Autowired
    private IIcOnHandNumService icOnHandNumService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertGeneralInByGeneralParam(GeneralParam generalParam, Long pkMember) {
        saveGeneralByParam(generalParam, pkMember);
    }

    @Override
    public void updateGeneralInByGeneralParam(IcGeneralInHExt generalInhExt, GeneralParam generalParam, Long pkMember) {
        // 更新规格明细表，先删除在新增 根据主表主键删除
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.GENERAL_IN.getValue(), generalInhExt.getPkId(), pkMember);
        generalInhExt.setPkCorp(generalParam.getPkCorp());
        generalInhExt.setPkOutCorp(generalParam.getPkOutCorp());
        generalInhExt.setPkCubasdoc(generalParam.getPkCubasdoc());
        generalInhExt.setPkWarehouse(generalParam.getPkWarehouse());
        generalInhExt.setPkOutWarehouse(generalParam.getPkOutWarehouse());
        generalInhExt.setOrderDate(generalParam.getOrderDate());
        generalInhExt.setRemark(generalParam.getRemark());
        // 更新订单明细表 分为3部分 删除的 新增的 修改的
        List<IcGeneralInB> generalInbList = getGeneralItems(generalParam, pkMember, generalInhExt);
        // 重新处理订单明细，将订单明细分为 删除的、新增的、修改的
        List<IcGeneralInBExt> icGeneralInbExtList = generalInhExt.getGeneralInbExtList();
        // 剩余的就是需要删除的
        Map<Long, IcGeneralInBExt> generalInbExtMap = icGeneralInbExtList.stream().collect(Collectors.toMap(IcGeneralInBExt::getPkId, generalInb->generalInb));
        List<IcGeneralInB> insertGeneralItems = new ArrayList<>();
        List<IcGeneralInB> updateGeneralItems = new ArrayList<>();
        List<ScmItemSpecs> saveScmItemSpecsList = new ArrayList<>();
        for (IcGeneralInB generalInB : generalInbList) {
            if (generalInB.getPkId() != null && generalInbExtMap.containsKey(generalInB.getPkId())) {
                // 修改的
                generalInB.setPkCreator(generalInbExtMap.get(generalInB.getPkId()).getPkCreator());
                updateGeneralItems.add(generalInB);
                saveScmItemSpecsList.addAll(generalInB.getScmItemSpecsList());
                generalInbExtMap.remove(generalInB.getPkId());
            } else {
                // 新增的
                generalInB.setPkGeneral(generalInhExt.getPkId());
                insertGeneralItems.add(generalInB);
            }
        }
        String generalLockKey = CacheConstants.IC_GENERAL_IN_LOCK + generalInhExt.getPkId();
        try {
            if (!redisService.lockKeyOnce(generalLockKey)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            if (insertGeneralItems.size() > 0) {
                // 保存订单明细 新增的
                generalInbService.saveBatch(insertGeneralItems);
                List<ScmItemSpecs> scmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(insertGeneralItems, generalInhExt.getPkId());
                if (scmItemSpecsList.size() > 0) {
                    saveScmItemSpecsList.addAll(scmItemSpecsList);
                }
            }
            if (updateGeneralItems.size() > 0) {
                // 修改订单明细 修改的
                updateGeneralItems.forEach(updateItems ->
                        generalInbService.updateById(updateItems));

            }
            if (generalInbExtMap.size() > 0) {
                // 删除订单明细 删除的
                List<IcGeneralInB> delGeneralItems = new ArrayList<>();
                generalInbExtMap.forEach((key, value) -> delGeneralItems.add(value));
                generalInbService.deleteGeneralItemsByList(delGeneralItems, pkMember);
            }
            // 保存订单明细规格
            if (saveScmItemSpecsList.size() > 0) {
                scmItemSpecsService.saveBatch(saveScmItemSpecsList);
            }
            // 更新订单表
            updateById(generalInhExt);
        } finally {
            redisService.unlock(generalLockKey);
        }
    }

    @Override
    public IcGeneralInHExt queryGeneralInById(Long pkId, Integer orderStatus) {
        return baseMapper.queryGeneralInById(pkId, orderStatus);
    }

    @Override
    public IcGeneralInHExt queryDisGeneralInExtById(Long pkId, Integer orderStatus) {
        GeneralParam generalParam = new GeneralParam();
        generalParam.setPkId(pkId);
        generalParam.setOrderStatus(orderStatus);
        List<IcGeneralInHExt> generalExtList = baseMapper.queryDisGeneralInExtByCondition(generalParam);
        if(CollectionUtil.isNotEmpty(generalExtList)){
            return generalExtList.get(0);
        }
        return null;
    }

    @Override
    public List<IcGeneralInHExt> queryDisGeneralInExtByCondition(GeneralParam generalParam) {
        if (generalParam.getEndDate() != null) {
            generalParam.setEndDate(DateUtils.afterDate(1, ChronoUnit.DAYS, generalParam.getEndDate()));
        }
        return baseMapper.queryDisGeneralInExtByCondition(generalParam);
    }

    @Override
    public void deleteGeneralIn(Long pkId, Long pkMember) {
        String generalInLock = CacheConstants.IC_GENERAL_IN_LOCK + pkId;
        if (!redisService.lockKeyOnce(generalInLock)) {
            throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
        }
        // 删除规格明细表
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.GENERAL_IN.getValue(), pkId, pkMember);
        generalInbService.deleteGeneralItemsByPkGeneral(pkId, pkMember);
        UpdateWrapper<IcGeneralInH> 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(generalInLock);
    }

    /*
     * @description: 将采购订单的参数转换为能保存的订单
     * @author: sui q
     * @date: 2023/11/20 15:53
     * @param: null null
     **/
    private void saveGeneralByParam(GeneralParam generalParam, Long pkMember) {
        IcGeneralInH icGeneralInH = BeanUtil.copyProperties(generalParam, IcGeneralInH.class);
        List<IcGeneralInB> generalItemList = getGeneralItems(generalParam, pkMember, icGeneralInH);
        // 生成单据号
        icGeneralInH.setOrderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.GENERAL_IN.getValue()));
        // 保存主表
        save(icGeneralInH);
        for (IcGeneralInB generalInB : generalItemList) {
            generalInB.setPkGeneral(icGeneralInH.getPkId());
        }
        // 保存子表
        generalInbService.saveBatch(generalItemList);
        List<ScmItemSpecs> saveScmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(generalItemList, icGeneralInH.getPkId());
        if (saveScmItemSpecsList.size() > 0) {
            scmItemSpecsService.saveBatch(saveScmItemSpecsList);
        }
    }

    private List<IcGeneralInB> getGeneralItems(GeneralParam generalParam, Long pkMember, IcGeneralInH icGeneralInH) {
        // 根据国家获得汇率
        CurrencyDTO currencyDTO = currencyServiceApi.getCurrency(generalParam.getPkCountry()).getData();
        SysUser sysUser = userServiceApi.selectUserById(pkMember).getData();
        // 根据登录账号获得部门
        icGeneralInH.setOrderType(EScmOrderType.GENERAL_IN.getValue());
        icGeneralInH.setPkDept(sysUser.getPkDept().intValue());
        icGeneralInH.setPkWhsmanager(pkMember);
        // 计算累计数量 累计价税合计
        // 总数量
        BigDecimal totalNum = BigDecimal.ZERO;
        List<IcGeneralInB> icGeneralInbList = new ArrayList<>();
        Date date = DateUtils.currentDateTime();
        for (GeneralBParam generalbParam : generalParam.getGeneralbParamList()) {
            IcGeneralInB generalInB = BeanUtil.copyProperties(generalbParam, IcGeneralInB.class);
            // 金额
            generalInB.setNcostmny(ComputeUtil.computeMultiply(generalInB.getNcostprice(), generalInB.getNnum()));
            generalInB.setPkRate(currencyDTO.getPkId());
            totalNum = ComputeUtil.computeAdd(totalNum, generalInB.getNnum());
            List<ItemSpecsParam> itemSpecsParamList = generalbParam.getScmItemSpecsList();
            scmItemSpecsService.packageScmItemByParam(itemSpecsParamList, generalInB, generalParam.getPkCountry(), pkMember,
                    icGeneralInH.getPkId(), generalInB.getPkId(), EScmOrderType.GENERAL_IN.getValue());
            icGeneralInbList.add(generalInB);
        }
        icGeneralInH.setPkCountry(generalParam.getPkCountry());
        if (generalParam.getPkId() == null) {
            icGeneralInH.setPkCreator(pkMember);
        } else {
            icGeneralInH.setPkModified(pkMember);
            icGeneralInH.setModifiedTime(date);
        }
        icGeneralInH.setTotalNum(totalNum);
        return icGeneralInbList;
    }

    private String approveGeneralByStatus(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);
        // 查询其他入库单
        IcGeneralInHExt generalInhExt = queryGeneralInById(scmOrderApproveLog.getPkOrder(), EScmOrderStatus.SUBMIT.getValue());
        if (generalInhExt == null) {
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_HAS_HANDLE);
        }
        // 更新采购入库单状态
        updateGeneralStatus(generalInhExt.getPkId(), approvalBusinessResultDTO.getLoginUser(), scmOrderStatus);
        // 更新前程日志表状态
        scmOrderApproveLogService.updateScmOrderApproveStatus(scmOrderApproveLog.getPkId(), approvalBusinessResultDTO.getLoginUser().getUserId(), approveStatus);
        if(EAgentApprovalStatus.APPROVED.getValue() == approveStatus){
            // 查询其他入库单明细表
            List<IcGeneralInBExt> generalInbExtList = generalInbService.queryGeneralInbByPk(EScmOrderType.GENERAL_IN.getValue(), generalInhExt.getGeneralInbExtList());
            if(generalInbExtList != null && generalInbExtList.size() >0){
                generalInhExt.setGeneralInbExtList(generalInbExtList);
            }
            // 更新现存量 // 更新采购订单累计入库数量
            icOnHandNumService.mergeIcOnHandNumByGeneralIn(generalInhExt, generalInhExt.getGeneralInbExtList(), EScmOrderType.GENERAL_IN.getValue(), approvalBusinessResultDTO.getLoginUser().getUserId());
        }
        return null;
    }

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

}
