package com.hw.wms.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import com.hw.common.core.constant.WmsConstants;
import com.hw.common.core.exception.ServiceException;
import com.hw.common.core.utils.uuid.Seq;
import com.hw.common.security.utils.SecurityUtils;
import com.hw.wms.domain.WmsInventoryCheckDetail;
import com.hw.wms.domain.*;
import com.hw.wms.domain.vo.WmsInventoryCheckDetailVo;
import com.hw.wms.domain.vo.WmsInventoryCheckVo;
import com.hw.wms.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Map;
import java.util.stream.Collectors;

import com.hw.common.core.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.hw.wms.service.IWmsInventoryCheckService;

/**
 * 盘点记录Service业务层处理
 *
 * @author xs
 * @date 2023-12-20
 */
@Service
public class WmsInventoryCheckServiceImpl implements IWmsInventoryCheckService {
    @Autowired
    private WmsInventoryCheckMapper wmsInventoryCheckMapper;

    @Autowired
    private WmsInventoryCheckDetailMapper wmsInventoryCheckDetailMapper;

    @Autowired
    private WmsBaseWarehouseMapper wmsBaseWarehouseMapper;

    @Autowired
    private WmsBaseLocationMapper wmsBaseLocationMapper;

    @Autowired
    private WmsRawStockMapper wmsRawStockMapper;

    @Autowired
    private WmsProductStockMapper wmsProductStockMapper;

    /**
     * 查询盘点记录
     *
     * @param inventoryCheckId 盘点记录主键
     * @return 盘点记录
     */
    @Override
    public WmsInventoryCheck selectWmsInventoryCheckByInventoryCheckId(Long inventoryCheckId) {
        return wmsInventoryCheckMapper.selectWmsInventoryCheckByInventoryCheckId(inventoryCheckId);
    }

    /**
     * 查询盘点记录列表
     *
     * @param wmsInventoryCheck 盘点记录
     * @return 盘点记录
     */
    @Override
    public List<WmsInventoryCheck> selectWmsInventoryCheckList(WmsInventoryCheck wmsInventoryCheck) {
        return wmsInventoryCheckMapper.selectWmsInventoryCheckList(wmsInventoryCheck);
    }

    /**
     * 新增盘点记录
     *
     * @param wmsInventoryCheckVo 进行盘点VO对象
     * @return 结果
     */
    @Transactional
    @Override
    public Long insertWmsInventoryCheck(WmsInventoryCheckVo wmsInventoryCheckVo) {
        Long inventoryCheckId = wmsInventoryCheckVo.getInventoryCheckId();
        Long toSetInventoryCheckId = inventoryCheckId;
        Long warehouseId = wmsInventoryCheckVo.getWarehouseId();
        List<String> locationCodes = wmsInventoryCheckVo.getLocationCodes();

        String userName = SecurityUtils.getUsername();
        Date currentDate = new Date();

        if (inventoryCheckId == null || inventoryCheckId.equals(0L) || inventoryCheckId.equals(-1L)) {
            WmsInventoryCheck queryInventoryCheck = new WmsInventoryCheck();
            queryInventoryCheck.setWarehouseId(warehouseId);
            queryInventoryCheck.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_STATUS_INVENTORYING);
            List<WmsInventoryCheck> wmsInventoryChecks = wmsInventoryCheckMapper.selectWmsInventoryCheckList(queryInventoryCheck);
            if (wmsInventoryChecks != null && !wmsInventoryChecks.isEmpty()) {
                throw new ServiceException("此仓库有未盘点完成的任务，请先盘点完成");
            }

            WmsBaseLocation queryLocation = new WmsBaseLocation();
            queryLocation.setWarehouseId(warehouseId);
            int locationAmount = wmsBaseLocationMapper.selectCountOfWmsBaseLocation(queryLocation);

            WmsInventoryCheck wmsInventoryCheck = new WmsInventoryCheck();
            wmsInventoryCheck.setInventoryCheckCode(Seq.getId(Seq.wmsInventoryCheckSeqType, Seq.wmsInventoryCheckSeqCode));
            wmsInventoryCheck.setWarehouseId(warehouseId);
            wmsInventoryCheck.setLocationAmount((long) locationAmount);
            wmsInventoryCheck.setInventoryingAmount((long) locationCodes.size());
            wmsInventoryCheck.setBeginTime(currentDate);
            wmsInventoryCheck.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_STATUS_INVENTORYING);
            wmsInventoryCheck.setCreateDate(currentDate);
            wmsInventoryCheck.setCreateBy(userName);
            wmsInventoryCheckMapper.insertWmsInventoryCheck(wmsInventoryCheck);

            toSetInventoryCheckId = wmsInventoryCheck.getInventoryCheckId();
        } else {
            WmsInventoryCheck toUpdatedInventoryCheck = wmsInventoryCheckMapper.selectWmsInventoryCheckByInventoryCheckId(inventoryCheckId);
            toUpdatedInventoryCheck.setInventoryingAmount(toUpdatedInventoryCheck.getInventoriedAmount() + (long) locationCodes.size());
            toUpdatedInventoryCheck.setUpdateDate(currentDate);
            toUpdatedInventoryCheck.setUpdateBy(userName);
            wmsInventoryCheckMapper.updateWmsInventoryCheck(toUpdatedInventoryCheck);
        }

        WmsBaseWarehouse baseWarehouse = wmsBaseWarehouseMapper.selectWmsBaseWarehouseByWarehouseId(warehouseId);
        String warehouseInstockType = baseWarehouse.getWarehouseInstockType();
        List<WmsInventoryCheckDetail> wmsInventoryCheckDetails = new ArrayList<>();

        for (String locationCode : locationCodes) {
            WmsBaseLocation location = wmsBaseLocationMapper.selectWmsBaseLocationByLocationCode(locationCode);
            if (location == null) {
                throw new ServiceException("没有库位[" + locationCode + "]");
            }
            if (!location.getLocationStatus().equals(WmsConstants.WMS_WAREHOUSE_TYPE_NORMAL)) {
                throw new ServiceException("库位[" + locationCode + "]状态锁定中，不能进行盘点");
            }

            //校验是否已经生成盘点记录明细(暂时不需要校验，有唯一索引)
//            if (inventoryCheckId != null && !inventoryCheckId.equals(0L)) {
//                int existedCount = wmsInventoryCheckDetailMapper.selectCountOfCheckDetailByCheckIdAndLocation(inventoryCheckId, locationCode);
//                if (existedCount > 0) {
//                    throw new ServiceException("已经生成库位[" + locationCode + "]的盘点记录，不能重复盘点");
//                }
//            }

            if (warehouseInstockType.equals(WmsConstants.WMS_WAREHOUSE_INSTOCK_TYPE_RAW)) {
                WmsRawStock queryRawStock = new WmsRawStock();
                queryRawStock.setLocationCode(locationCode);
                List<WmsRawStock> wmsRawStocks = wmsRawStockMapper.selectWmsRawStockInList(queryRawStock);
                if (wmsRawStocks != null && !wmsRawStocks.isEmpty()) {
                    for (WmsRawStock wmsRawStock : wmsRawStocks) {
                        WmsInventoryCheckDetail wmsInventoryCheckDetail = new WmsInventoryCheckDetail();
                        wmsInventoryCheckDetail.setMaterialId(wmsRawStock.getMaterialId());
                        wmsInventoryCheckDetail.setMaterialBatch(wmsRawStock.getInstockBatch());
                        wmsInventoryCheckDetail.setInventoryTime(0L);
                        wmsInventoryCheckDetail.setStockType(WmsConstants.RWA_STOCK_STOCK_TYPE_RAW);
                        wmsInventoryCheckDetail.setStockId(wmsRawStock.getRawStockId());
                        wmsInventoryCheckDetail.setLocationCode(locationCode);
                        wmsInventoryCheckDetail.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_INVENTORYING);
                        wmsInventoryCheckDetail.setCreateDate(currentDate);
                        wmsInventoryCheckDetail.setCreateBy(userName);
                        wmsInventoryCheckDetail.setInventoryCheckId(toSetInventoryCheckId);
                        wmsInventoryCheckDetails.add(wmsInventoryCheckDetail);
                    }
                } else {//如果库位没有库存也要增加数据
                    WmsInventoryCheckDetail wmsInventoryCheckDetail = new WmsInventoryCheckDetail();
                    wmsInventoryCheckDetail.setInventoryTime(0L);
                    wmsInventoryCheckDetail.setLocationCode(locationCode);
                    wmsInventoryCheckDetail.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_INVENTORYING);
                    wmsInventoryCheckDetail.setCreateDate(currentDate);
                    wmsInventoryCheckDetail.setCreateBy(userName);
                    wmsInventoryCheckDetail.setInventoryCheckId(toSetInventoryCheckId);
                    wmsInventoryCheckDetails.add(wmsInventoryCheckDetail);
                }

            } else {
                WmsProductStock queryProductStock = new WmsProductStock();
                queryProductStock.setLocationCode(locationCode);
                List<WmsProductStock> wmsProductStocks = wmsProductStockMapper.selectWmsProductStockInList(queryProductStock);
                if (wmsProductStocks != null && !wmsProductStocks.isEmpty()) {
                    for (WmsProductStock wmsProductStock : wmsProductStocks) {
                        WmsInventoryCheckDetail wmsInventoryCheckDetail = new WmsInventoryCheckDetail();
                        wmsInventoryCheckDetail.setMaterialId(wmsProductStock.getProductId());
                        wmsInventoryCheckDetail.setMaterialBatch(wmsProductStock.getProductBatch());
                        wmsInventoryCheckDetail.setStockType(wmsProductStock.getStockType());
                        wmsInventoryCheckDetail.setStockId(wmsProductStock.getProductStockId());
                        wmsInventoryCheckDetail.setInventoryTime(0L);
                        wmsInventoryCheckDetail.setLocationCode(locationCode);
                        wmsInventoryCheckDetail.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_INVENTORYING);
                        wmsInventoryCheckDetail.setCreateDate(currentDate);
                        wmsInventoryCheckDetail.setCreateBy(userName);
                        wmsInventoryCheckDetail.setInventoryCheckId(toSetInventoryCheckId);
                        wmsInventoryCheckDetails.add(wmsInventoryCheckDetail);
                    }
                } else {
                    WmsInventoryCheckDetail wmsInventoryCheckDetail = new WmsInventoryCheckDetail();
                    wmsInventoryCheckDetail.setInventoryTime(0L);
                    wmsInventoryCheckDetail.setLocationCode(locationCode);
                    wmsInventoryCheckDetail.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_INVENTORYING);
                    wmsInventoryCheckDetail.setCreateDate(currentDate);
                    wmsInventoryCheckDetail.setCreateBy(userName);
                    wmsInventoryCheckDetail.setInventoryCheckId(toSetInventoryCheckId);
                    wmsInventoryCheckDetails.add(wmsInventoryCheckDetail);
                }
            }
        }

        if (wmsInventoryCheckDetails.size() > 0) {
            wmsInventoryCheckMapper.batchWmsInventoryCheckDetail(wmsInventoryCheckDetails);
        }

        return toSetInventoryCheckId;
    }

    /**
     * 修改盘点记录
     *
     * @param wmsInventoryCheck 盘点记录
     * @return 结果
     */
    @Transactional
    @Override
    public int updateWmsInventoryCheck(WmsInventoryCheck wmsInventoryCheck) {
        wmsInventoryCheckMapper.deleteWmsInventoryCheckDetailByInventoryCheckId(wmsInventoryCheck.getInventoryCheckId());
        return wmsInventoryCheckMapper.updateWmsInventoryCheck(wmsInventoryCheck);
    }

    /**
     * 批量删除盘点记录
     *
     * @param inventoryCheckIds 需要删除的盘点记录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteWmsInventoryCheckByInventoryCheckIds(Long[] inventoryCheckIds) {
        wmsInventoryCheckMapper.deleteWmsInventoryCheckDetailByInventoryCheckIds(inventoryCheckIds);
        return wmsInventoryCheckMapper.deleteWmsInventoryCheckByInventoryCheckIds(inventoryCheckIds);
    }

    /**
     * 删除盘点记录信息
     *
     * @param inventoryCheckId 盘点记录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteWmsInventoryCheckByInventoryCheckId(Long inventoryCheckId) {
        wmsInventoryCheckMapper.deleteWmsInventoryCheckDetailByInventoryCheckId(inventoryCheckId);
        return wmsInventoryCheckMapper.deleteWmsInventoryCheckByInventoryCheckId(inventoryCheckId);
    }

    /**
     * 新增盘点记录明细信息
     *
     * @param wmsInventoryCheckDetailList 盘点记录明细列表
     * @param inventoryCheckId            盘点记录ID
     */
    public void insertWmsInventoryCheckDetail(List<WmsInventoryCheckDetail> wmsInventoryCheckDetailList, Long inventoryCheckId) {
        if (StringUtils.isNotNull(wmsInventoryCheckDetailList)) {
            List<WmsInventoryCheckDetail> list = new ArrayList<WmsInventoryCheckDetail>();
            for (WmsInventoryCheckDetail wmsInventoryCheckDetail : wmsInventoryCheckDetailList) {
                wmsInventoryCheckDetail.setInventoryCheckId(inventoryCheckId);
                list.add(wmsInventoryCheckDetail);
            }
            if (list.size() > 0) {
                wmsInventoryCheckMapper.batchWmsInventoryCheckDetail(list);
            }
        }
    }


    /**
     * 查询盘点记录列表,join warehouse
     *
     * @param wmsInventoryCheck 盘点记录
     * @return 盘点记录
     */
    @Override
    public List<WmsInventoryCheck> selectWmsInventoryCheckJoinList(WmsInventoryCheck wmsInventoryCheck) {
        return wmsInventoryCheckMapper.selectWmsInventoryCheckJoinList(wmsInventoryCheck);
    }

//    /**
//     * 根据判断状态获取数据，按状态返回list数据
//     *
//     * @param wmsInventoryCheckDetail
//     * @return
//     */
//    @Override
//    public Map<String, List<WmsInventoryCheckDetail>> getIncompletedInventoryCheckDetailsMap(WmsInventoryCheckDetail wmsInventoryCheckDetail) {
//        wmsInventoryCheckDetail.setCheckStatusStr(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_TO_INVENTORY + "," + WmsConstants.WMS_INVENTORY_CHECK_STATUS_INVENTORYING);
//        List<WmsInventoryCheckDetail> wmsInventoryCheckDetailList = wmsInventoryCheckDetailMapper.selectWmsInventoryCheckDetailJoinList(wmsInventoryCheckDetail);
//
//        Map<String, List<WmsInventoryCheckDetail>> checkDetailMap =
//                wmsInventoryCheckDetailList.stream().filter(checkDetail -> StringUtils.isNotEmpty(checkDetail.getCheckStatus())).collect(Collectors.groupingBy(WmsInventoryCheckDetail::getCheckStatus));
//
//        return checkDetailMap;
//    }


    /**
     * 根据判断状态获取数据，按状态返回list数据
     *
     * @param wmsInventoryCheckDetail
     * @return
     */
    @Override
    public List<WmsInventoryCheckDetail> getInventoryCheckDetails(WmsInventoryCheckDetail wmsInventoryCheckDetail) {
        List<WmsInventoryCheckDetail> wmsInventoryCheckDetailList = wmsInventoryCheckDetailMapper.selectWmsInventoryCheckDetailJoinList(wmsInventoryCheckDetail);
        return wmsInventoryCheckDetailList;
    }


    /**
     * 确认盘点
     *
     * @param wmsInventoryCheckDetailVo
     * @return
     */
    @Override
    public int confirmInventoryCheckDetail(WmsInventoryCheckDetailVo wmsInventoryCheckDetailVo) {
        WmsInventoryCheckDetail existedInventoryCheckDetail = wmsInventoryCheckDetailMapper.
                selectWmsInventoryCheckDetailByInventoryCheckDetailId(wmsInventoryCheckDetailVo.getInventoryCheckDetailId());
        if (existedInventoryCheckDetail.getCheckStatus().equals(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_FINISH)) {
            throw new ServiceException("已经盘点完成，不能再确认");
        }

        String stockType = existedInventoryCheckDetail.getStockType();
        Long stockId = existedInventoryCheckDetail.getStockId();
        BigDecimal realAmount = wmsInventoryCheckDetailVo.getRealAmount();
        Long inventoryTime = existedInventoryCheckDetail.getInventoryTime() == null ? 0L : existedInventoryCheckDetail.getInventoryTime();
        existedInventoryCheckDetail.setInventoryTime(inventoryTime + 1);
        existedInventoryCheckDetail.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_INVENTORYING);
        if (stockId != null) {
            if (stockType.equals(WmsConstants.WMS_WAREHOUSE_INSTOCK_TYPE_RAW)) {
                WmsRawStock rawStock = wmsRawStockMapper.selectWmsRawStockByRawStockId(stockId);
                BigDecimal stockAmount = rawStock == null ? BigDecimal.ZERO : rawStock.getTotalAmount();
                existedInventoryCheckDetail.setStockAmount(stockAmount);
            } else {
                WmsProductStock productStock = wmsProductStockMapper.selectWmsProductStockByProductStockId(stockId);
                BigDecimal stockAmount = productStock == null ? BigDecimal.ZERO : productStock.getTotalAmount();
                existedInventoryCheckDetail.setStockAmount(stockAmount);
            }
        } else {
            if (realAmount.compareTo(BigDecimal.ZERO) > 0) {
                throw new ServiceException("此库位无库存信息，实际盘库数量需等于0");
            }
        }

        existedInventoryCheckDetail.setRealAmount(realAmount);
        existedInventoryCheckDetail.setUpdateDate(new Date());
        existedInventoryCheckDetail.setUpdateBy(SecurityUtils.getUsername());

        return wmsInventoryCheckDetailMapper.updateWmsInventoryCheckDetail(existedInventoryCheckDetail);
    }


    /**
     * 盘点完成
     *
     * @param wmsInventoryCheck
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int completeInventoryCheck(WmsInventoryCheck wmsInventoryCheck) {
        List<WmsInventoryCheckDetail> wmsInventoryCheckDetailList = wmsInventoryCheck.getWmsInventoryCheckDetailList();
        List<WmsInventoryCheckDetail> unconfirmedCheckDetails = wmsInventoryCheckDetailList.stream()
                .filter(checkDetail -> checkDetail.getInventoryTime() < 1).collect(Collectors.toList());
        if (unconfirmedCheckDetails != null && !unconfirmedCheckDetails.isEmpty()) {
            throw new ServiceException("请先全部确认后再点击盘点完成");
        }

        Map<String, List<WmsInventoryCheckDetail>> inventoryCheckDetailMap = wmsInventoryCheckDetailList.stream()
                .collect(Collectors.groupingBy(WmsInventoryCheckDetail::getLocationCode));
        long completeLocationAmount = inventoryCheckDetailMap.entrySet().size();

//        List<Long> inventoryCheckDetailIds = wmsInventoryCheckDetailList.stream().map(WmsInventoryCheckDetail::getInventoryCheckDetailId).collect(Collectors.toList());
        Date currentDate = new Date();
        String userName = SecurityUtils.getUsername();
        wmsInventoryCheckDetailList.forEach(wmsInventoryCheckDetail -> {
            wmsInventoryCheckDetail.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_DETAIL_STATUS_FINISH);
            wmsInventoryCheckDetail.setUpdateDate(currentDate);
            wmsInventoryCheckDetail.setUpdateBy(userName);
            wmsInventoryCheckDetailMapper.updateWmsInventoryCheckDetail(wmsInventoryCheckDetail);
        });

        WmsInventoryCheck existedInventoryCheck = wmsInventoryCheckMapper.selectOnlyInventoryCheckByInventoryCheckId(wmsInventoryCheck.getInventoryCheckId());
        Long inventoriedAmount = existedInventoryCheck.getInventoriedAmount();
        Long locationAmount = existedInventoryCheck.getLocationAmount();
        Long currentInventoriedAmount = inventoriedAmount + completeLocationAmount;
        wmsInventoryCheck.setInventoriedAmount(currentInventoriedAmount);
        wmsInventoryCheck.setUpdateDate(currentDate);
        wmsInventoryCheck.setUpdateBy(userName);
        if (currentInventoriedAmount >= locationAmount) {
            wmsInventoryCheck.setCheckStatus(WmsConstants.WMS_INVENTORY_CHECK_STATUS_FINISH);
            wmsInventoryCheck.setEndTime(currentDate);
        }
        return wmsInventoryCheckMapper.updateWmsInventoryCheck(wmsInventoryCheck);
    }
}
