package com.ruoyi.oa.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.SysOaWarehouse;
import com.ruoyi.oa.domain.bo.SysOaOutWarehouseBo2;
import com.ruoyi.oa.domain.bo.SysOaOutWarehouseBoList;
import com.ruoyi.oa.domain.vo.SysOaOutWarehouseListVo;
import com.ruoyi.oa.domain.vo.SysOaProjectVo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseVo;
import com.ruoyi.oa.mapper.SysOaProjectMapper;
import com.ruoyi.oa.mapper.SysOaWarehouseDetailMapper;
import com.ruoyi.oa.mapper.SysOaWarehouseMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseDetailVo;
import com.ruoyi.oa.domain.SysOaWarehouseDetail;
import com.ruoyi.oa.service.ISysOaWarehouseDetailService;

import java.util.*;

import static cn.hutool.core.bean.BeanUtil.*;

/**
 * 仓库出库Service业务层处理
 *
 * @author liuzongkun999
 * @date 2024-11-02
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysOaWarehouseDetailServiceImpl implements ISysOaWarehouseDetailService {

    private final SysOaWarehouseDetailMapper baseMapper;


    @Autowired
    private SysOaWarehouseMapper warehouseMapper;

    @Autowired
    private SysOaProjectMapper projectMapper;


    /**
     * 查询仓库出库
     */
    @Override
    public SysOaWarehouseDetailVo queryById(Long id){
        SysOaWarehouseDetailVo sysOaWarehouseDetailVo = baseMapper.selectVoById(id);
        SysOaWarehouseVo sysOaWarehouse = warehouseMapper.selectVoByIdAndXml(sysOaWarehouseDetailVo.getWarehouseId());
        SysOaProjectVo sysOaProject = projectMapper.selectVoById(sysOaWarehouseDetailVo.getProjectId());
        sysOaWarehouseDetailVo.setWarehouse(sysOaWarehouse);

        // 出库可能不关联项目
        if (Objects.nonNull(sysOaProject)){
            sysOaWarehouseDetailVo.setProject(sysOaProject);
        }
        return sysOaWarehouseDetailVo;
    }


    /**
     * 查询仓库出库产品id的列表
     *
     * @param WarehouseId 出库产品id
     */
    @Override
    public TableDataInfo<SysOaWarehouseDetailVo> queryWarehouseIdList(Long WarehouseId) {
        LambdaQueryWrapper<SysOaWarehouseDetail> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysOaWarehouseDetail::getWarehouseId, WarehouseId);
        for (SysOaWarehouseDetailVo sysOaWarehouseDetailVo : baseMapper.selectVoList(lqw)) {
            sysOaWarehouseDetailVo.setWarehouseName( warehouseMapper.selectById(sysOaWarehouseDetailVo.getWarehouseId()).getName());
        }
        return TableDataInfo.build(baseMapper.selectVoList(lqw));
    }


    /**
     * 查询仓库出库列表
     */

    @Override
    public TableDataInfo<SysOaOutWarehouseListVo> queryPageList(SysOaWarehouseDetailBo bo, PageQuery pageQuery) {
        Long total = baseMapper.defineQueryTotal(bo, pageQuery);

        pageQuery.setPageNum(ObjectUtil.defaultIfNull(pageQuery.getPageNum(), 1));
        pageQuery.setPageSize(ObjectUtil.defaultIfNull(pageQuery.getPageSize(), Integer.MAX_VALUE));
        if (pageQuery.getPageNum() <= 0) {
            pageQuery.setPageNum(1);
        }
        if (pageQuery.getPageSize() <= 0) {
            pageQuery.setPageSize(Integer.MAX_VALUE);
        }
        pageQuery.setPageNum((pageQuery.getPageNum() - 1)*pageQuery.getPageSize());
        List<SysOaOutWarehouseListVo> selectList = baseMapper.defineSelectList(bo, pageQuery);

        IPage<SysOaOutWarehouseListVo> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        page.setRecords(selectList);
        page.setTotal(total);

        return TableDataInfo.build(page);
    }

    /**
     * 查询仓库出库列表
     */
    @Override
    public List<SysOaWarehouseDetailVo> queryList(SysOaWarehouseDetailBo bo) {
        LambdaQueryWrapper<SysOaWarehouseDetail> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysOaWarehouseDetail> buildQueryWrapper(SysOaWarehouseDetailBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysOaWarehouseDetail> lqw = Wrappers.lambdaQuery();

        lqw.eq(bo.getProjectId() != null, SysOaWarehouseDetail::getProjectId, bo.getProjectId());
        lqw.eq(bo.getAmount() != null, SysOaWarehouseDetail::getAmount, bo.getAmount());
        lqw.eq(bo.getWarehouseId() != null, SysOaWarehouseDetail::getWarehouseId, bo.getWarehouseId());
        lqw.eq(bo.getFatherId() != null, SysOaWarehouseDetail::getFatherId, bo.getFatherId());
        lqw.eq(bo.getMasterId() != null, SysOaWarehouseDetail::getMasterId, bo.getMasterId());

        return lqw;
    }

    /**
     * 新增出入库细节
     */
    @Override
    public Boolean insertByBo(SysOaWarehouseDetailBo bo) {
        SysOaWarehouseDetail decrease = toBean(bo, SysOaWarehouseDetail.class);
        validEntityBeforeSave(decrease);

        if (Objects.isNull(bo.getType()) || bo.getType() != 1L) {
            SysOaWarehouse warehouse = warehouseMapper.selectById(decrease.getWarehouseId());
            // 1  如果对应仓库表项目数量-将要出库数量<0，出库失败, 繁殖 ， 增加该条
            if(warehouse == null) {
                throw new Error("已不存在该物料"+decrease.getWarehouseId());
            }
            if(warehouse.getInventory() - decrease.getAmount() < 0) {
                throw new Error("剩余数量不足,出库失败");
            }
            else {
                warehouse.setInventory(warehouse.getInventory() - decrease.getAmount());
                warehouse.setUpdateTime(new Date());
                warehouseMapper.updateById(warehouse);
            }
        }
        return baseMapper.insert(decrease) > 0;
    }

    /**
     * 仓库批量出库
     */
    @Override
    public Boolean insertByBoList(SysOaOutWarehouseBoList boList) {


        Long projectId = boList.getProjectId();
        List<SysOaOutWarehouseBo2> list = boList.getOutWareHouseList();
        if (projectId != null) {
            list.forEach((sysOaOutWarehouseBo2 -> {
                sysOaOutWarehouseBo2.setProjectId(projectId);
                SysOaWarehouseDetailBo sysOaOutWarehouse = toBean(sysOaOutWarehouseBo2, SysOaWarehouseDetailBo.class);
                insertByBo(sysOaOutWarehouse);
            }));

        }else{
            list.forEach((sysOaOutWarehouseBo2 -> {
                SysOaWarehouseDetailBo sysOaOutWarehouse = toBean(sysOaOutWarehouseBo2, SysOaWarehouseDetailBo.class);
                insertByBo(sysOaOutWarehouse);
            }));
        }


          return true;
    }

    /**
     * 修改仓库出库
     */
    @Override
    public Boolean updateByBo(SysOaWarehouseDetailBo bo) {
        SysOaWarehouseDetail update = toBean(bo, SysOaWarehouseDetail.class);
        validEntityBeforeSave(update);

        // 修改后的数量
        Long amount1 = update.getAmount();

        //获得 修改前的数量
        SysOaWarehouseDetail sysOaWarehouseDetail = baseMapper.selectById(update.getId());
        Long amount = sysOaWarehouseDetail.getAmount();

        //找出库存表对应的那条数据 的库存数量
        LambdaQueryWrapper<SysOaWarehouse> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysOaWarehouse::getId, update.getWarehouseId());
        SysOaWarehouse warehouse = warehouseMapper.selectOne(lqw);
        Long inventory = warehouse.getInventory();

        //出库多了
        if(amount1 > amount) {
            //确保出库不超余量
            if(amount1-amount<=inventory) {
                //可以减少差值
                baseMapper.updateById(update);
                warehouse.setInventory(inventory -( amount1 - amount));
                warehouseMapper.updateById(warehouse);
            }
            else {
                throw new Error("库存数量不足，无法增加出库数量");
            }
        }
        else {
            //确保出库不能为负
            if (amount1 > 0) {
                //此时增加差值
                baseMapper.updateById(update);
                warehouse.setInventory(warehouse.getInventory() + amount - amount1);
                warehouseMapper.updateById(warehouse);
            }
            else {
                throw new Error("出库数量不能为负");
            }
        }
        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysOaWarehouseDetail entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除仓库出库
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //需要增加的对应物料数量
        LambdaQueryWrapper<SysOaWarehouseDetail> lqw = Wrappers.lambdaQuery();
        lqw.in(SysOaWarehouseDetail::getId, ids.toArray());
        //出库表中的所有删除的数据
        List<SysOaWarehouseDetail> sysOaWarehouseDetails = baseMapper.selectList(lqw);
        //其中一条
        sysOaWarehouseDetails.forEach(sysOaWarehouseDetail -> {
            //选出相对应的 库存表中那一条的数据
            SysOaWarehouse warehouse = warehouseMapper.selectVoByIdAndXml(sysOaWarehouseDetail.getWarehouseId());
            // 恢复原本出库的数量
            warehouse.setInventory(warehouse.getInventory() + sysOaWarehouseDetail.getAmount());
            warehouseMapper.updateById(warehouse);
        });
        return  baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据项目id查出库
     * @param projectId
     * @return
     */
    @Override
    public TableDataInfo<SysOaWarehouseDetailVo> queryOutWarehouseByProjectId(Long projectId) {
        LambdaQueryWrapper<SysOaWarehouseDetail> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysOaWarehouseDetail::getProjectId, projectId);
        List<SysOaWarehouseDetailVo> sysOaWarehouseDetailVos = baseMapper.selectVoList(lqw);
        for (SysOaWarehouseDetailVo sysOaWarehouseDetailVo : sysOaWarehouseDetailVos) {
           sysOaWarehouseDetailVo.setWarehouseName(warehouseMapper.selectVoByIdAndXml((sysOaWarehouseDetailVo.getWarehouseId())).getName());
        }
        return TableDataInfo.build(sysOaWarehouseDetailVos);
    }

    /**
     * 删除detail的简单方法
     * @param id
     */
    @Override
    public void deleteById(Long id) {
        baseMapper.deleteById(id);
    }


}
