package com.patzn.lims.consume.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.patzn.cloud.commons.toolkit.BigDecimalUtils;
import com.patzn.lims.consume.dto.LmsChemicalStockDTO;
import com.patzn.lims.consume.entity.LmsChemical;
import com.patzn.lims.consume.entity.LmsChemicalPurchaseOrder;
import com.patzn.lims.consume.entity.LmsChemicalRelPurchase;
import com.patzn.lims.consume.entity.LmsChemicalStock;
import com.patzn.lims.consume.enums.PurchaseOrderEnum;
import com.patzn.lims.consume.enums.PurchaseRelStateEnum;
import com.patzn.lims.consume.enums.StockUserecordEnum;
import com.patzn.lims.consume.mapper.LmsChemicalStockMapper;
import com.patzn.lims.consume.service.*;
import com.patzn.lims.core.api.PtAssert;
import com.patzn.lims.core.web.BaseServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.patzn.lims.res.entity.LmsSupplier;
import com.patzn.lims.res.service.ILmsSupplierService;
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.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 试验耗材库存表 服务实现类
 * </p>
 *
 * @author wwd
 * @since 2020-03-24
 */
@Service
public class LmsChemicalStockServiceImpl extends BaseServiceImpl<LmsChemicalStockMapper, LmsChemicalStock> implements ILmsChemicalStockService {


    @Autowired
    private ILmsChemicalService lmsChemicalService;

    @Autowired
    private ILmsChemicalClassifyService lmsChemicalClassifyService;

    @Autowired
    private ILmsChemicalRelPurchaseService lmsChemicalRelPurchaseService;

    @Autowired
    private ILmsChemicalPurchaseOrderService lmsChemicalPurchaseOrderService;

    @Autowired
    private ILmsChemicalUserecordService lmsChemicalUserecordService;

    @Autowired
    private ILmsSupplierService lmsSupplierService;

    public Page<LmsChemicalStock> page(Page<LmsChemicalStock> page, LmsChemicalStock lmsChemicalStock) {
        QueryWrapper<LmsChemicalStock> wrapper = Wrappers.<LmsChemicalStock>query(lmsChemicalStock);
        return this.page(page, wrapper);
    }

    @Override
    public Page<LmsChemicalStockDTO> page(Page<LmsChemicalStockDTO> page, LmsChemicalStockDTO dto) {
        List<LmsChemicalStockDTO> list = baseMapper.pageDTO(page, dto);
        list.stream().filter(o -> null != o.getValidDate()).forEach(o -> {
            Date today = new Date();
            Date validDay = o.getValidDate();
            long from1 = today.getTime();
            long to1 = validDay.getTime();
            o.setValidDay((int) ((to1 - from1) / (1000 * 60 * 60 * 24)));
        });
        return page.setRecords(list);
    }



    @Override
    public boolean saveDTO(LmsChemicalStockDTO stockDTO) {
        if (null == stockDTO.getChemicalId()) {
            return false;
        }
        LmsChemicalStock chemicalStock=  stockDTO.convert(LmsChemicalStock.class);

        LmsChemical chemical = lmsChemicalService.getById(chemicalStock.getChemicalId());
        if (null == chemical || null == chemicalStock.getStock()) {
            PtAssert.fail("耗材 ID 不存在无效入库操作！");
        }
        //首次入库数据
        //    if(chemicalStock instanceof LmsChemicalStockDTO ) {
        vaildfristStock(chemicalStock.getProductCode(), chemicalStock.getBatchNum(), chemicalStock.getChemicalId());
        //  }

        vaildProdcutCode(chemical.getId(), chemicalStock.getProductCode());
        // 出入库记录
        if (null != chemical.getUnit()
                && null != chemical.getExchange()
        ) {
            chemicalStock.setExstock(BigDecimalUtils.mul(chemicalStock.getStock(), chemical.getExchange()));
        }
        chemicalStock.setUnit(chemical.getUnit());
        chemicalStock.setExunit(chemical.getExunit());

        LmsChemicalStock tempStock = chemicalStock.convert(LmsChemicalStock.class);
        LmsChemicalStockDTO tempDto = chemicalStock.convert(LmsChemicalStockDTO.class);
        //同时更新耗材表和耗材库存表单件字段为最新的
        if (null != tempDto.getPrice()) {
            tempStock.setUnitPrice(tempDto.getPrice());
            LmsChemical savechemical = new LmsChemical();
            savechemical.setUnitPrice(tempDto.getPrice());
            lmsChemicalService.update(savechemical, Wrappers.<LmsChemical>query().eq("id", chemical.getId()));
        }
        if (super.save(tempStock)) {
            //保存供应商
            validSupplierIsExist(tempStock.getSupplier());
            LmsChemicalStockDTO dto = chemicalStock.convert(LmsChemicalStockDTO.class);
            dto.setStorehouse(chemical.getStorehouse());
            dto.setAllstock(chemical.getStock());//添加耗材总库存
            dto.setId(tempStock.getId());
            return updateStockRecord(chemical, dto, StockUserecordEnum.IN_STOCK);
        }
        return false;
    }


    public void vaildfristStock(String productCode, String batchNum, Long chemicalId) {
        if (super.count(Wrappers.<LmsChemicalStock>query().eq("chemical_id", chemicalId).eq("product_code", productCode).eq("batch_num", batchNum)) > 0) {
            PtAssert.fail("已经存在此耗材对应批次，请直接入库即可");
        }
    }


    public void vaildProdcutCode(Long chemicalId, String productCode) {
        if (StringUtils.isNotBlank(productCode)) {
            LmsChemicalStock chemicalIdObj = super.getOne(Wrappers.<LmsChemicalStock>query().select("chemical_id")
                    .eq("product_code", productCode).last("LIMIT 1"));
            if (null != chemicalIdObj && !chemicalIdObj.equals(chemicalId)) {
                PtAssert.fail("该商品编码其它耗材已经使用，请更换其它编码。");
            }
        }
    }

    private void validSupplierIsExist(String supplierName) {
        if (StringUtils.isNotBlank(supplierName)) {
            List<LmsSupplier> lst = lmsSupplierService.listByName(supplierName);
            if (CollectionUtils.isEmpty(lst)) {
                LmsSupplier supplier = new LmsSupplier();
                supplier.setName(supplierName);
                lmsSupplierService.save(supplier);
            }
        }

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateDTOById(LmsChemicalStockDTO dto) {
        if (null == dto.getId() || null == dto.getType()) {
            return false;
        }
        LmsChemicalStock chemicalStock = super.getById(dto.getId());
        if (null == chemicalStock) {
            PtAssert.fail("库存不在，无效操作！");
        }
        LmsChemical lmsChemical = lmsChemicalService.getById(chemicalStock.getChemicalId());
        if (null == lmsChemical) {
            PtAssert.fail("库存相关耗材不在，无效操作！");
        }
        LmsChemicalStock tempStock = new LmsChemicalStock();
        tempStock.setId(dto.getId());
        if (null != dto.getRemark()) {
            tempStock.setRemark(dto.getRemark());
        }
        // 转换库存量
        BigDecimal exstock = BigDecimalUtils.mul(dto.getStock(), lmsChemical.getExchange());
        StockUserecordEnum stockUserecordEnum = StockUserecordEnum.valueOf(dto.getType());

        // 入库、输入数量，备注信息
        if (stockUserecordEnum == StockUserecordEnum.IN_STOCK) {
            tempStock.setStock(BigDecimalUtils.add(chemicalStock.getStock(), dto.getStock()));
            tempStock.setExstock(BigDecimalUtils.add(chemicalStock.getExstock(), exstock));
        }

        // 使用出库
        else if (stockUserecordEnum == StockUserecordEnum.OUT_STOCK) {
            tempStock.setStock(BigDecimalUtils.sub(chemicalStock.getStock(), dto.getStock()));
            tempStock.setExstock(BigDecimalUtils.sub(chemicalStock.getExstock(), exstock));
            if (BigDecimalUtils.lessThan(tempStock.getStock(), BigDecimal.ZERO)) {
                PtAssert.fail("出库数量大于库存数量，请重新输入！");
            }
            tempStock.setExused(BigDecimalUtils.add(chemicalStock.getExused(), exstock));
        }
        //库存校正
        else if (stockUserecordEnum == StockUserecordEnum.CHECK) {
            tempStock.setStock(BigDecimalUtils.add(chemicalStock.getStock(), dto.getStock()));
            tempStock.setExstock(BigDecimalUtils.add(chemicalStock.getExstock(), exstock));
            if (BigDecimalUtils.lessThan(tempStock.getStock(), BigDecimal.ZERO)) {
                PtAssert.fail("库存校正后库存量小于0，请重新输入！");
            }
        }
        else if (stockUserecordEnum == StockUserecordEnum.GIVE_BACK) {
            if(null != dto.getExstock() && null != dto.getStock() && dto.getExstock().compareTo(BigDecimalUtils.mul(dto.getStock(),lmsChemical.getExchange())) == 1){
                PtAssert.fail("归还库存量有误，请重新输入。");

            }
            tempStock.setStock(BigDecimalUtils.add(chemicalStock.getStock(), dto.getStock()));
            tempStock.setExstock(BigDecimalUtils.add(chemicalStock.getExstock(), dto.getExstock()));
            tempStock.setExused(BigDecimalUtils.sub(chemicalStock.getExused(), dto.getExstock()));
            // 使用量为负数设置为零
            if (BigDecimalUtils.lessThan(tempStock.getExused(), BigDecimal.ZERO)) {
                tempStock.setExused(BigDecimal.ZERO);
            }
            exstock = dto.getExstock();
        }

        //入库记录的价格更新为耗材表的单价和耗材库存表的单价
        if (null != dto.getPrice()) {
            tempStock.setUnitPrice(dto.getPrice());
            LmsChemical chemical = new LmsChemical();
            chemical.setUnitPrice(dto.getPrice());
            lmsChemicalService.update(chemical, Wrappers.<LmsChemical>query().eq("id", lmsChemical.getId()));
        }

        // 库存记录
        dto.setExstock(exstock);
        dto.setAllstock(lmsChemical.getStock());//添加保存耗材总库存
        dto.setBatchStock(chemicalStock.getStock());//添加保存批次库存
        dto.setBatchNum(chemicalStock.getBatchNum());
        dto.setStorehouse(lmsChemical.getStorehouse());
        dto.setValidDate(chemicalStock.getValidDate());
        dto.setChemicalId(chemicalStock.getChemicalId());
        if (updateStockRecord(lmsChemical, dto, stockUserecordEnum)) {
            return super.updateById(tempStock);
        }
        return false;
    }

    @Override
    public boolean updateStockRecord(LmsChemical chemical, LmsChemicalStockDTO dto, StockUserecordEnum stockUserecordEnum) {
        boolean add = true;
        // 1、修改耗材库存及转换库存量
        LmsChemical tempChemical = new LmsChemical();
        tempChemical.setId(chemical.getId());
        //保证
        tempChemical.setNum(chemical.getNum());
        tempChemical.setCategory(chemical.getCategory());
        if (stockUserecordEnum == StockUserecordEnum.IN_STOCK
                || stockUserecordEnum == StockUserecordEnum.GIVE_BACK
                || stockUserecordEnum == StockUserecordEnum.CHECK) {
            // 入库、归还
            tempChemical.setStock(BigDecimalUtils.add(chemical.getStock(), dto.getStock()));
            tempChemical.setExstock(BigDecimalUtils.add(chemical.getExstock(), dto.getExstock()));
        } else {
            // 出库
            tempChemical.setStock(BigDecimalUtils.sub(chemical.getStock(), dto.getStock()));
            tempChemical.setExstock(BigDecimalUtils.sub(chemical.getExstock(), dto.getExstock()));
            add = false;
        }
        // 1、更新耗材库存量
        if (lmsChemicalService.updateById(tempChemical)
                // 2、修改归类库存量
                && lmsChemicalClassifyService.addStockByChemicalId(chemical.getId(), dto.getExstock(), add)
        ) {
            //判斷是否是采购单入库
            // 正常、调整 允许入库
            if (null != dto.getPurchaseOrderRelId()) {
                // 修改订单行入库量
                LmsChemicalRelPurchase lcrp = lmsChemicalRelPurchaseService.getById(dto.getPurchaseOrderRelId());
                if (PurchaseRelStateEnum.NORMAL.getValue() == lcrp.getState()
                        || PurchaseRelStateEnum.ADJUST.getValue() == lcrp.getState()
                        || PurchaseRelStateEnum.END_PURCHASE.getValue() == lcrp.getState()
                        || PurchaseRelStateEnum.STOCK.getValue() == lcrp.getState()) {

                    LmsChemicalRelPurchase tempLcrp = new LmsChemicalRelPurchase();
                    tempLcrp.setId(dto.getPurchaseOrderRelId());
                    tempLcrp.setAlreadyQuantity(BigDecimalUtils.add(dto.getStock(), lcrp.getAlreadyQuantity()));
                    //入库修改耗材关联表为入库状态
                    tempLcrp.setState(PurchaseRelStateEnum.STOCK.getValue());
                    lmsChemicalRelPurchaseService.updateById(tempLcrp);
                    //同时修改采购单为部分入库状态
                    //如果采购单为待采购状态，看其下耗材状态，
                    // 如果有“正常”和“调整”的，则采购单为“采购中”，
                    // 如有“已入库”无“正常”和“调整”，则采购单为“部分入库”
                    // 如全部为“结束”，则采购单为“完成”(此种情况不可能，因为入库按钮不可能使所有耗材为结束状态)
                    LmsChemicalPurchaseOrder order = new LmsChemicalPurchaseOrder();
                    List<LmsChemicalRelPurchase> relList = lmsChemicalRelPurchaseService.list(Wrappers.<LmsChemicalRelPurchase>query().eq("order_id", lcrp.getOrderId()));
                    if (CollectionUtils.isEmpty(relList)) {
                        return false;
                    }
                    List<Integer> relStateList = relList.stream().map(o -> o.getState()).collect(Collectors.toList());
                    if (relStateList.contains(PurchaseRelStateEnum.NORMAL.getValue())
                            || relStateList.contains(PurchaseRelStateEnum.ADJUST.getValue())) {
                        order.setStatus(PurchaseOrderEnum.PURCHASEING.getValue());
                    } else if (relStateList.contains(PurchaseRelStateEnum.STOCK.getValue())
                            && !relStateList.contains(PurchaseRelStateEnum.NORMAL.getValue())
                            && !relStateList.contains(PurchaseRelStateEnum.ADJUST.getValue())) {
                        order.setStatus(PurchaseOrderEnum.STOCK_PART.getValue());
                    }
                    order.setId(lcrp.getOrderId());
                    lmsChemicalPurchaseOrderService.updateById(order);
                } else {
                    PtAssert.fail("该采购单行，不允许入库操作。");
                }
            }
            if (null == dto.getUnit()) {
                dto.setUnit(chemical.getUnit());
            }
            if (null == dto.getExunit()) {
                dto.setExunit(chemical.getExunit());
            }
            dto.setAllstock(tempChemical.getStock());
            // 3、记录入库记录
            return lmsChemicalUserecordService.saveStockRecord(stockUserecordEnum, dto);


        }
        return false;
    }
}
