package com.fjhx.victoriatourist.service.stock.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.victoriatourist.entity.abnormal.po.AbnormalInfo;
import com.fjhx.victoriatourist.entity.stock.dto.StockTransferDto;
import com.fjhx.victoriatourist.entity.stock.dto.StockTransferSelectDto;
import com.fjhx.victoriatourist.entity.stock.po.StockTransfer;
import com.fjhx.victoriatourist.entity.stock.po.StockTransferDetails;
import com.fjhx.victoriatourist.entity.stock.vo.StockTransferDetailsVo;
import com.fjhx.victoriatourist.entity.stock.vo.StockTransferVo;
import com.fjhx.victoriatourist.mapper.stock.StockTransferMapper;
import com.fjhx.victoriatourist.service.abnormal.AbnormalInfoService;
import com.fjhx.victoriatourist.service.stock.StockTransferDetailsService;
import com.fjhx.victoriatourist.service.stock.StockTransferService;
import com.fjhx.victoriatourist.utils.CodeEnum;
import com.fjhx.wms.entity.stock.dto.StockJournalDetailsDto;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.po.Stock;
import com.fjhx.wms.entity.stock.po.StockJournal;
import com.fjhx.wms.entity.stock.po.StockJournalDetails;
import com.fjhx.wms.service.stock.StockJournalDetailsService;
import com.fjhx.wms.service.stock.StockJournalService;
import com.fjhx.wms.service.stock.StockService;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 调仓记录 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-17
 */
@Service
public class StockTransferServiceImpl extends ServiceImpl<StockTransferMapper, StockTransfer> implements StockTransferService {

    @Autowired
    WarehouseService warehouseService;
    @Autowired
    StockTransferDetailsService stockTransferDetailsService;
    @Autowired
    ProductInfoService productInfoService;
    @Autowired
    StockService stockService;
    @Autowired
    StockJournalService stockJournalService;
    @Autowired
    StockJournalDetailsService stockJournalDetailsService;
    @Autowired
    AbnormalInfoService abnormalInfoService;

    @Override
    public Page<StockTransferVo> getPage(StockTransferSelectDto dto) {
        IWrapper<StockTransfer> wrapper = getWrapper();
        wrapper.eq(StockTransfer::getInWarehouseId, dto.getInWarehouseId());
        wrapper.eq(StockTransfer::getOutWarehouseId, dto.getOutWarehouseId());
        wrapper.eq(StockTransfer::getInStatus, dto.getInStatus());
        wrapper.like(StockTransfer::getCode, dto.getKeyword());
        wrapper.orderByDesc("st", StockTransfer::getId);
        Page<StockTransferVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<StockTransferVo> records = page.getRecords();
        //赋值仓库名称
        warehouseService.attributeAssign(records, StockTransferVo::getInWarehouseId, (item, warehouse) -> {
            item.setInWarehouseName(warehouse.getName());
        });
        warehouseService.attributeAssign(records, StockTransferVo::getOutWarehouseId, (item, warehouse) -> {
            item.setOutWarehouseName(warehouse.getName());
        });
        //赋值调出人与接收人名称
        UserUtil.assignmentNickName(records, StockTransferVo::getCreateUser, StockTransferVo::setOutUserName);
        UserUtil.assignmentNickName(records, StockTransferVo::getInUserId, StockTransferVo::setInUserName);
        return page;
    }

    @Override
    public StockTransferVo detail(Long id) {
        StockTransfer StockTransfer = this.getById(id);
        StockTransferVo result = BeanUtil.toBean(StockTransfer, StockTransferVo.class);
        //赋值仓库名称信息
        warehouseService.attributeAssign(Arrays.asList(result), StockTransferVo::getInWarehouseId, (item, warehouse) -> {
            item.setInWarehouseName(warehouse.getName());
        });
        warehouseService.attributeAssign(Arrays.asList(result), StockTransferVo::getOutWarehouseId, (item, warehouse) -> {
            item.setOutWarehouseName(warehouse.getName());
        });
        List<StockTransferDetails> list = stockTransferDetailsService.list(q -> q.eq(StockTransferDetails::getStockTransferId, id));
        List<StockTransferDetailsVo> stockTransferDetailsVos = BeanUtil.copyToList(list, StockTransferDetailsVo.class);
        //赋值明细产品信息
        productInfoService.attributeAssign(stockTransferDetailsVos, StockTransferDetailsVo::getProductId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCode());
            item.setProductName(productInfo.getName());
            item.setProductSpec(productInfo.getSpec());
        });
        result.setStockTransferDetailsList(stockTransferDetailsVos);
        return result;
    }

    @DSTransactional
    @Override
    public void add(StockTransferDto stockTransferDto) {
        Assert.notEmpty(stockTransferDto.getOutWarehouseId(), "出库仓库不能为空");
        Assert.notEmpty(stockTransferDto.getInWarehouseId(), "入库仓库不能为空");
        Assert.notEmpty(stockTransferDto.getStockTransferDetailsList(), "调仓明细不能为空");

        stockTransferDto.setCode(CodeEnum.STOCK_TRANSFER.getCode());
        stockTransferDto.setType(1);
        stockTransferDto.setInStatus(0);
        this.save(stockTransferDto);
        List<StockTransferDetails> stockTransferDetailsList = stockTransferDto.getStockTransferDetailsList();
        List<Stock> stockList = new ArrayList<>();

        //创建出库记录
        StockJournal stockJournal1 = new StockJournal();
        stockJournal1.setOpType(2);
        stockJournal1.setType(JournalType.ADJUSTING_OUT.getDetailType());
        stockJournal1.setCode(stockTransferDto.getCode());
        stockJournal1.setWarehouseId(stockTransferDto.getOutWarehouseId());
        stockJournal1.setBusinessId(stockTransferDto.getId());
        //保存出库记录
        stockJournalService.save(stockJournal1);

        List<StockJournalDetails> stockJournalDetailsList1 = new ArrayList<>();
        for (StockTransferDetails stockTransferDetails : stockTransferDetailsList) {
            Stock stock = new Stock();
            stock.setProductId(stockTransferDetails.getProductId());
            stock.setQuantity(stockTransferDetails.getOutQuantity());
            stockList.add(stock);

            //创建出入库明细
            StockJournalDetails stockJournalDetails = new StockJournalDetailsDto();
            stockJournalDetails.setStockJournalId(stockJournal1.getId());
            stockJournalDetails.setProductId(stock.getProductId());
            stockJournalDetails.setQuantity(stock.getQuantity());
            stockJournalDetails.setBusinessDetailsId(stockTransferDetails.getId());
            stockJournalDetailsList1.add(stockJournalDetails);

            stockTransferDetails.setStockTransferId(stockTransferDto.getId());
        }
        stockTransferDetailsService.saveBatch(stockTransferDetailsList);


        if (ObjectUtil.isNotEmpty(stockList)) {
            //出库
            stockService.ModifyInventory(2, stockList, stockTransferDto.getOutWarehouseId());
            //保存出库记录明细
            stockJournalDetailsService.saveBatch(stockJournalDetailsList1);
        }
    }

    @Override
    public void edit(StockTransferDto stockTransferDto) {
        this.updateById(stockTransferDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    @DSTransactional
    @Override
    public void receive(StockTransferDto stockTransferDto) {
        StockTransfer stockTransfer = getById(stockTransferDto.getId());
        stockTransfer.setInStatus(2);//修改为已接收
        stockTransfer.setInUserId(SecurityUtils.getUserId());//赋值接收人
        stockTransfer.setInTime(new Date());//赋值接收时间

        List<StockJournalDetails> stockJournalDetailsList = new ArrayList<>();

        //明细
        List<Stock> stockList = new ArrayList<>();
        List<StockTransferDetails> stockTransferDetailsList = stockTransferDto.getStockTransferDetailsList();
        if (ObjectUtil.isNotEmpty(stockTransferDetailsList)) {
            //获取数据库中的数据
            List<Long> ids = stockTransferDetailsList.stream().map(StockTransferDetails::getId).collect(Collectors.toList());
            List<StockTransferDetails> oldstockTransferDetailsList = stockTransferDetailsService.listByIds(ids);
            Map<Long, StockTransferDetails> oldstockTransferDetailsMap = oldstockTransferDetailsList.stream().collect(Collectors.toMap(StockTransferDetails::getId, Function.identity()));

            //创建入库记录
            StockJournal stockJournal = new StockJournal();
            stockJournal.setOpType(1);
            stockJournal.setType(JournalType.ADJUSTING_IN.getDetailType());
            stockJournal.setCode(stockTransfer.getCode());
            stockJournal.setWarehouseId(stockTransfer.getInWarehouseId());
            stockJournal.setBusinessId(stockTransfer.getId());
            //保存人库记录
            stockJournalService.save(stockJournal);

            Integer abnormalFlag = 0;
            for (StockTransferDetails stockTransferDetails : stockTransferDetailsList) {
                Stock stock = new Stock();
                stock.setProductId(stockTransferDetails.getProductId());
                stock.setQuantity(stockTransferDetails.getInQuantity());
                stockList.add(stock);

                //创建出入库明细
                StockJournalDetails stockJournalDetails = new StockJournalDetailsDto();
                stockJournalDetails.setStockJournalId(stockJournal.getId());
                stockJournalDetails.setProductId(stock.getProductId());
                stockJournalDetails.setQuantity(stock.getQuantity());
                stockJournalDetails.setBusinessDetailsId(stockTransferDetails.getId());
                stockJournalDetailsList.add(stockJournalDetails);

                //调仓接收数量与发出数量不一致
                StockTransferDetails oldstockTransferDetails = oldstockTransferDetailsMap.get(stockTransferDetails.getId());
                if (stockTransferDetails.getInQuantity().compareTo(oldstockTransferDetails.getOutQuantity()) != 0) {
                    abnormalFlag = 1;
                }


                //计算已入库数量
                BigDecimal inCount = oldstockTransferDetails.getInQuantity().add(stockTransferDetails.getInQuantity());
                if (inCount.compareTo(oldstockTransferDetails.getOutQuantity()) != 0) {
                    stockTransfer.setInStatus(1);//设置为部分接收
                }
                stockTransferDetails.setInQuantity(inCount);
            }
            if (abnormalFlag == 1) {
                AbnormalInfo abnormalInfo = new AbnormalInfo();
                abnormalInfo.setId(IdWorker.getId());
                abnormalInfo.setStatus(0);
                abnormalInfo.setType(30);
                abnormalInfo.setLinkId(stockTransfer.getId());
                abnormalInfo.setLinkCode(stockTransfer.getCode());
                abnormalInfo.setTitle("调仓接收数量与发出数量不一致");
                abnormalInfoService.save(abnormalInfo);
            }

            //修改质检信息
            stockTransferDetailsService.updateBatchById(stockTransferDetailsList);
        }
        updateById(stockTransfer);


        if (ObjectUtil.isNotEmpty(stockList)) {
            //入库
            stockService.ModifyInventory(1, stockList, stockTransfer.getInWarehouseId());
            //保存入库记录明细
            stockJournalDetailsService.saveBatch(stockJournalDetailsList);
        }
    }

    @Override
    @DSTransactional
    public void stockTransfer(StockTransferDto stockTransferDto) {
        Assert.notEmpty(stockTransferDto.getOutWarehouseId(), "出库仓库不能为空");
        Assert.notEmpty(stockTransferDto.getInWarehouseId(), "入库仓库不能为空");
        Assert.notEmpty(stockTransferDto.getStockTransferDetailsList(), "调仓明细不能为空");

        stockTransferDto.setCode(CodeEnum.STOCK_TRANSFER.getCode());
        stockTransferDto.setType(1);
        stockTransferDto.setInStatus(2);//已接收
        this.save(stockTransferDto);
        List<StockTransferDetails> stockTransferDetailsList = stockTransferDto.getStockTransferDetailsList();
        for (StockTransferDetails stockTransferDetails : stockTransferDetailsList) {
            stockTransferDetails.setStockTransferId(stockTransferDto.getId());
            stockTransferDetails.setInQuantity(stockTransferDetails.getOutQuantity());
        }
        stockTransferDetailsService.saveBatch(stockTransferDetailsList);

        List<Stock> stockList = new ArrayList<>();
        for (StockTransferDetails stockTransferDetails : stockTransferDetailsList) {
            Stock stock = new Stock();
            stock.setProductId(stockTransferDetails.getProductId());
            stock.setQuantity(stockTransferDetails.getOutQuantity());
            stockList.add(stock);
        }

        //创建出库记录
        StockJournal stockJournal = new StockJournal();
        stockJournal.setCode(stockTransferDto.getCode());
        stockJournal.setOpType(2);//出库
        stockJournal.setType(JournalType.ADJUSTING_OUT.getDetailType());//调仓入库
        stockJournal.setWarehouseId(stockTransferDto.getOutWarehouseId());
        stockJournal.setBusinessId(stockTransferDto.getId());
        stockJournalService.save(stockJournal);
        List<StockJournalDetails> stockJournalDetailsList = new ArrayList<>();
        for (StockTransferDetails stockTransferDetails : stockTransferDetailsList) {
            //创建出库明细
            StockJournalDetails stockJournalDetails = new StockJournalDetailsDto();
            stockJournalDetails.setStockJournalId(stockJournal.getId());
            stockJournalDetails.setProductId(stockTransferDetails.getProductId());
            stockJournalDetails.setQuantity(stockTransferDetails.getOutQuantity());
            stockJournalDetails.setBusinessDetailsId(stockTransferDetails.getId());
            stockJournalDetailsList.add(stockJournalDetails);
        }
        //操作库存
        stockService.ModifyInventory(2, stockList, stockTransferDto.getOutWarehouseId());
        //保存出库记录明细
        stockJournalDetailsService.saveBatch(stockJournalDetailsList);

        //创建入库记录
        StockJournal stockJournal1 = new StockJournal();
        stockJournal1.setCode(stockTransferDto.getCode());
        stockJournal1.setBusinessId(stockTransferDto.getId());
        stockJournal1.setOpType(1);//入库
        stockJournal1.setType(JournalType.ADJUSTING_IN.getDetailType());//调仓出库
        stockJournal1.setWarehouseId(stockTransferDto.getInWarehouseId());
        stockJournalService.save(stockJournal1);
        //入库操作
        stockService.ModifyInventory(1, stockList, stockTransferDto.getInWarehouseId());
        //保存入库记录明细
        for (StockJournalDetails stockJournalDetails : stockJournalDetailsList) {
            //清空id再插入一份入库记录
            stockJournalDetails.setId(null);
            //赋值入库流水主表id
            stockJournalDetails.setStockJournalId(stockJournal1.getId());
        }
        stockJournalDetailsService.saveBatch(stockJournalDetailsList);
    }

}
