package com.fjhx.wms.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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.entity.InOutBo;
import com.fjhx.common.utils.Assert;
import com.fjhx.file.utils.ObsFileUtil;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.wms.entity.stock.dto.StockJournalDetailsDto;
import com.fjhx.wms.entity.stock.dto.StockWaitDto;
import com.fjhx.wms.entity.stock.dto.StockWaitSelectDto;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.po.*;
import com.fjhx.wms.entity.stock.vo.StockWaitDetailsVo;
import com.fjhx.wms.entity.stock.vo.StockWaitVo;
import com.fjhx.wms.entity.warehouse.po.Warehouse;
import com.fjhx.wms.mapper.stock.StockWaitMapper;
import com.fjhx.wms.service.MyPurchaseService;
import com.fjhx.wms.service.stock.*;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.fjhx.wms.utils.CodeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 待出入库 服务实现类
 * </p>
 *
 * @since 2023-03-22
 */
@Service
public class StockWaitServiceImpl extends ServiceImpl<StockWaitMapper, StockWait> implements StockWaitService {
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private StockService stockService;
    @Autowired
    private StockJournalService stockJournalService;
    @Autowired
    private StockJournalDetailsService stockJournalDetailsService;
    @Autowired
    private StockWaitDetailsService stockWaitDetailsService;
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private MyPurchaseService myPurchaseService;

    @Override
    public Page<StockWaitVo> getPage(StockWaitSelectDto dto) {
        IWrapper<StockWait> wrapper = getWrapper();
        //过滤入库/出库
        wrapper.eq(StockWait::getType, dto.getType());
        wrapper.eq("sw", StockWait::getBusinessType, dto.getBusinessType());
        wrapper.eq(StockWait::getBusinessCode, dto.getKeyword());
        wrapper.orderByDesc("sw", StockWait::getId);
        Page<StockWaitVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<StockWaitVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return page;
        }

        //赋值明细列表
        setDetailsInfo(records);

        return page;
    }

    private void setDetailsInfo(List<StockWaitVo> records) {
        //获取明细列表
        List<Long> swIds = records.stream().map(StockWait::getId).collect(Collectors.toList());
        List<StockWaitDetails> list = stockWaitDetailsService.list(q -> q.in(StockWaitDetails::getStockWaitId, swIds));
        List<StockWaitDetailsVo> voList = BeanUtil.copyToList(list, StockWaitDetailsVo.class);
        productInfoService.attributeAssign(voList, StockWaitDetails::getProductId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCustomCode());
            item.setProductCustomCode(productInfo.getCustomCode());
            item.setProductName(productInfo.getName());
            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductHeight(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());

            item.setProductUnit(productInfo.getUnit());
            item.setProductType(productInfo.getType());
            item.setProductSpec(productInfo.getSpec());
            item.setProductDefinition(productInfo.getDefinition());
        });
        Map<Long, List<StockWaitDetailsVo>> voMap = voList.stream().collect(Collectors.groupingBy(StockWaitDetails::getStockWaitId));

        //赋值明细列表
        records.forEach(item -> item.setStockWaitDetailsList(voMap.get(item.getId())));
    }

    @Override
    public StockWaitVo detail(Long id) {
        StockWait stockWait = this.getById(id);
        StockWaitVo result = BeanUtil.toBean(stockWait, StockWaitVo.class);

        //赋值产品明细列表
        setDetailsInfo(Collections.singletonList(result));

        return result;
    }

    @DSTransactional
    @Override
    public void add(StockWaitDto stockWaitDto) {
        Long warehouseId = stockWaitDto.getWarehouseId();
        Warehouse warehouse = warehouseService.getById(warehouseId);
        if (ObjectUtil.isEmpty(warehouse)) {
            throw new ServiceException("查询不到仓库信息！");
        }
        Long companyId = warehouse.getCompanyId();

        Assert.notEmpty(stockWaitDto.getId(), "待出入库id不能为空");
        Assert.notEmpty(warehouseId, "仓库id不能为空");

        List<Stock> stockList = new ArrayList<>();

        List<StockWaitDetails> stockWaitDetailsDtoList = stockWaitDto.getStockWaitDetailsList();

        //过滤数量为空,为零的数据
        stockWaitDetailsDtoList = stockWaitDetailsDtoList.stream()
                .filter(item -> ObjectUtil.isNotEmpty(item.getQuantity()) && item.getQuantity().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.toList());

        //更新已出入库数量以及待出入库状态
        stockWaitDetailsService.changeStockWaitStatus(stockWaitDto);
        StockWait stockWait = getById(stockWaitDto.getId());
        updateById(stockWait);

        //操作库存
        List<Long> swdIds = stockWaitDetailsDtoList.stream().map(StockWaitDetails::getId).collect(Collectors.toList());
        Map<Long, StockWaitDetails> oldStockWaitDetailsMap = stockWaitDetailsService.mapKEntity(StockWaitDetails::getId, q -> q.in(StockWaitDetails::getId, swdIds));

        //创建出入库记录
        Integer businessType = stockWait.getBusinessType();
        JournalType journalType = JournalType.getByDetailType(businessType);
        StockJournal stockJournal = new StockJournal();
        stockJournal.setOpType(stockWait.getType());//根据待入库类型赋值操作类型 1入库 2出库
        stockJournal.setType(journalType.getDetailType());
        stockJournal.setCode(stockWait.getType() == 1 ? CodeEnum.SIN_CODE.getCode() : CodeEnum.SOUT_CODE.getCode());
        stockJournal.setWarehouseId(warehouseId);
        stockJournal.setBusinessId(stockWaitDto.getId());
        stockJournal.setCompanyId(companyId);
        //保存出入库记录
        stockJournalService.save(stockJournal);

        //保存待入库附件
        ObsFileUtil.saveFile(stockWaitDto.getFileList(), stockJournal.getId());

        List<StockJournalDetails> stockJournalDetailsList = new ArrayList<>();
        for (StockWaitDetails waitDetails : stockWaitDetailsDtoList) {
            StockWaitDetails temp = oldStockWaitDetailsMap.get(waitDetails.getId());
            Stock stock = new Stock();
            stock.setQuantity(waitDetails.getQuantity());
            stock.setProductId(temp.getProductId());
            stockList.add(stock);

            //创建出入库明细
            StockJournalDetails stockJournalDetails = new StockJournalDetailsDto();
            stockJournalDetails.setStockJournalId(stockJournal.getId());
            stockJournalDetails.setProductId(stock.getProductId());
            stockJournalDetails.setQuantity(stock.getQuantity());
            stockJournalDetails.setBusinessDetailsId(waitDetails.getId());
            stockJournalDetails.setCompanyId(companyId);
            stockJournalDetailsList.add(stockJournalDetails);
        }
        List<InOutBo> inOutBoList = BeanUtil.copyToList(stockList, InOutBo.class);

        //操作库存根据待出入库类型来1入库2出库
        stockService.changeStock(inOutBoList, warehouseId, journalType);
        //保存出入库明细
        stockJournalDetailsService.saveBatch(stockJournalDetailsList);
    }

    @Override
    public void edit(StockWaitDto stockWaitDto) {
        this.updateById(stockWaitDto);
    }

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

    @Override
    public void updateStatus(Long id) {
        StockWait stockWait = this.getById(id);
        Assert.notEmpty(stockWait, "查询不到待出入库信息");

        long count = stockWaitDetailsService.count(q -> q
                .eq(StockWaitDetails::getStockWaitId, id)
                .ne(StockWaitDetails::getStatus, 2)
        );

        //存在非完成数据 部分完成
        if (count > 0) {
            stockWait.setStatus(1);
            long count1 = stockWaitDetailsService.count(q -> q
                    .eq(StockWaitDetails::getStockWaitId, id)
                    .eq(StockWaitDetails::getStatus, 1)
            );
            //不存在部分完成数据 未开始
            if (count1 == 0) {
                stockWait.setStatus(0);
            }
        }

        this.updateById(stockWait);
    }

}
