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

import cn.hutool.core.util.ObjectUtil;
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.entity.InOutBo;
import com.fjhx.common.enums.InOutType;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.wms.entity.stock.dto.StockCheckDto;
import com.fjhx.wms.entity.stock.dto.StockCheckSelectDto;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.po.StockCheck;
import com.fjhx.wms.entity.stock.po.StockCheckDetails;
import com.fjhx.wms.entity.stock.po.StockJournal;
import com.fjhx.wms.entity.stock.po.StockJournalDetails;
import com.fjhx.wms.entity.stock.vo.StockCheckDetailsVo;
import com.fjhx.wms.entity.stock.vo.StockCheckVo;
import com.fjhx.wms.entity.warehouse.po.Warehouse;
import com.fjhx.wms.mapper.stock.StockCheckMapper;
import com.fjhx.wms.service.stock.*;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.fjhx.wms.utils.CodeEnum;
import com.ruoyi.common.constant.StatusConstant;
import com.ruoyi.common.exception.ServiceException;
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 org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Objects;


/**
 * <p>
 * 库存盘点 服务实现类
 * </p>
 *
 * @author
 * @since 2023-03-22
 */
@Service
public class StockCheckServiceImpl extends ServiceImpl<StockCheckMapper, StockCheck> implements StockCheckService {

    @Autowired
    private StockCheckDetailsService stockCheckDetailsService;

    @Autowired
    private ProductInfoService productInfoService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private StockJournalService stockJournalService;
    @Autowired
    private StockJournalDetailsService stockJournalDetailsService;
    @Autowired
    private StockWaitService stockWaitService;
    @Autowired
    private StockService stockService;

    @Override
    public Page<StockCheckVo> getPage(StockCheckSelectDto dto) {
        IWrapper<StockCheck> wrapper = getWrapper();
        wrapper.like("sc", StockCheckVo::getCreateTime, dto.getKeyword());
        wrapper.eq("sc", StockCheck::getResult, dto.getResult());
        wrapper.orderByDesc("sc", StockCheck::getId);
        Page<StockCheckVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<StockCheckVo> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        // 根据id赋值操作人名称
        UserUtil.assignmentNickName(page.getRecords(), StockCheckVo::getCreateUser, StockCheckVo::setUserName);

        // 赋值仓库名称
        warehouseService.attributeAssign(records, StockCheck::getWarehouseId, (item, warehouse) -> {
            item.setWarehouseName(warehouse.getName());
        });

        return page;
    }

    @Override
    public StockCheckVo detail(Long id) {
        StockCheckVo stockCheckVo = baseMapper.detail(id);

        List<StockCheckDetailsVo> list = stockCheckVo.getList();
        if(ObjectUtil.isEmpty(list)){
            return stockCheckVo;
        }
        productInfoService.attributeAssign(list, StockCheckDetails::getProductId, (item, product) -> {
            item.setProductCode(product.getCode());
            item.setProductName(product.getName());
            item.setProductUnit(product.getUnit());
        });
        return stockCheckVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(StockCheckDto stockCheckDto) {

        long stockCheckId = IdWorker.getId();
        List<StockCheckDetails> list = stockCheckDto.getList();
        int totalNum = 0, normalNum = 0, anomalyNum = 0;

        Long warehouseId = stockCheckDto.getWarehouseId();
        Warehouse warehouse = warehouseService.getById(warehouseId);
        if (ObjectUtil.isEmpty(warehouse)) {
            throw new ServiceException("查询不到仓库信息！");
        }
        Long companyId = warehouse.getCompanyId();

        for (StockCheckDetails stockCheckDetails : list) {

            totalNum++;

            if (Objects.equals(stockCheckDetails.getQuantity(), stockCheckDetails.getCheckQuantity())) {
                normalNum++;
            } else {
                anomalyNum++;

                //盘点数和库存不一样 需要创建流水修正
                if (stockCheckDetails.getQuantity().compareTo(stockCheckDetails.getCheckQuantity()) > 0) {
                    //盘亏 出库
                    BigDecimal subtract = stockCheckDetails.getQuantity().subtract(stockCheckDetails.getCheckQuantity());

                    //创建出库记录
                    StockJournal stockJournal = new StockJournal();
                    stockJournal.setOpType(2);
                    stockJournal.setType(JournalType.STOCK_CHECK_OUT.getDetailType());
                    stockJournal.setCode(CodeEnum.SOUT_CODE.getCode());
                    stockJournal.setWarehouseId(warehouseId);
                    stockJournal.setBusinessId(stockCheckId);
                    stockJournal.setCompanyId(companyId);
                    stockJournalService.save(stockJournal);
                    //创建出库明细(并计算结存单价)
                    StockJournalDetails stockJournalDetails = stockService.calculateUnitPrice(InOutType.OUT, stockCheckDetails.getProductId(), warehouseId, subtract, 0, null);
                    stockJournalDetails.setStockJournalId(stockJournal.getId());
                    stockJournalDetails.setProductId(stockCheckDetails.getProductId());
                    stockJournalDetails.setQuantity(subtract);
                    stockJournalDetails.setBusinessDetailsId(stockCheckDetails.getId());
                    stockJournalDetails.setCompanyId(companyId);
                    stockJournalDetailsService.save(stockJournalDetails);
                    //出库操作
                    InOutBo inOutBo = new InOutBo();
                    inOutBo.setProductId(stockCheckDetails.getProductId());
                    inOutBo.setQuantity(subtract);
                    stockService.changeStock(Collections.singletonList(inOutBo), warehouseId, JournalType.STOCK_CHECK_OUT);
                } else {
                    //盘盈 入库
                    BigDecimal subtract = stockCheckDetails.getCheckQuantity().subtract(stockCheckDetails.getQuantity());

                    //创建入库记录
                    StockJournal stockJournal = new StockJournal();
                    stockJournal.setOpType(1);
                    stockJournal.setType(JournalType.STOCK_CHECK_IN.getDetailType());
                    stockJournal.setCode(CodeEnum.SIN_CODE.getCode());
                    stockJournal.setWarehouseId(warehouseId);
                    stockJournal.setBusinessId(stockCheckId);
                    stockJournal.setCompanyId(companyId);
                    stockJournalService.save(stockJournal);
                    //创建入库明细(并计算结存单价)
                    StockJournalDetails stockJournalDetails = stockService.calculateUnitPrice(InOutType.IN, stockCheckDetails.getProductId(), warehouseId, subtract, 0, null);
                    stockJournalDetails.setStockJournalId(stockJournal.getId());
                    stockJournalDetails.setProductId(stockCheckDetails.getProductId());
                    stockJournalDetails.setQuantity(subtract);
                    stockJournalDetails.setBusinessDetailsId(stockCheckDetails.getId());
                    stockJournalDetails.setCompanyId(companyId);
                    stockJournalDetailsService.save(stockJournalDetails);
                    //入库操作
                    InOutBo inOutBo = new InOutBo();
                    inOutBo.setProductId(stockCheckDetails.getProductId());
                    inOutBo.setQuantity(subtract);
                    stockService.changeStock(Collections.singletonList(inOutBo), warehouseId, JournalType.STOCK_CHECK_IN);
                }

            }

            stockCheckDetails.setStockCheckId(stockCheckId);
        }

        stockCheckDto.setId(stockCheckId);
        stockCheckDto.setCode(CodeEnum.CHECK_CODE.getCode());
        stockCheckDto.setResult(anomalyNum > 0 ? StatusConstant.YES : StatusConstant.NO);
        stockCheckDto.setTotalNum(totalNum);
        stockCheckDto.setNormalNum(normalNum);
        stockCheckDto.setAnomalyNum(anomalyNum);

        // 保存盘点记录以及明细
        save(stockCheckDto);
        stockCheckDetailsService.saveBatch(list);
    }

}
