package cn.iocoder.yudao.module.basic.service.goodsinfo;

import cn.iocoder.yudao.framework.common.enums.CodeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.basic.api.redis.RedisBasicInfoUtilApi;
import cn.iocoder.yudao.module.basic.controller.admin.goodsinfo.vo.*;
import cn.iocoder.yudao.module.basic.convert.goodsinfo.GoodsInfoConvert;
import cn.iocoder.yudao.module.basic.dal.dataobject.dealergoods.DealerGoodsDO;
import cn.iocoder.yudao.module.basic.dal.dataobject.goodsinfo.GoodsInfoDO;
import cn.iocoder.yudao.module.basic.dal.dataobject.unit.UnitDO;
import cn.iocoder.yudao.module.basic.dal.mysql.dealergoods.DealerGoodsMapper;
import cn.iocoder.yudao.module.basic.dal.mysql.goodsinfo.GoodsInfoMapper;
import cn.iocoder.yudao.module.basic.dal.mysql.unit.UnitMapper;
import cn.iocoder.yudao.module.basic.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.basic.service.businessinfo.BusinessInfoServiceImpl;
import cn.iocoder.yudao.module.product.api.harvestbatch.HarvestBatchApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.basic.enums.ErrorCodeConstants.*;

/**
 * 商品 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class GoodsInfoServiceImpl implements GoodsInfoService {

    @Resource
    private GoodsInfoMapper goodsInfoMapper;

    @Resource
    private DealerGoodsMapper dealerGoodsMapper;

    @Resource
    private RedisBasicInfoUtilApi redisUtil;

    @Resource
    private BusinessInfoServiceImpl businessInfoService;

    @Resource
    private HarvestBatchApi harvestBatchApi;

    @Resource
    private UnitMapper unitMapper;

    /**
     * 创建商品
     *
     * @param createReqVO 创建信息
     * @return
     */
    @Override
    public Long createGoodsInfo(GoodsInfoCreateReqVO createReqVO) {
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(createReqVO.getBelongBusinessId());
        //商品名称进行唯一校验
        validateGoodsNameExists(createReqVO.getGoodsName());
        // 插入
        GoodsInfoDO goodsInfo = GoodsInfoConvert.INSTANCE.convert(createReqVO);
        try {
            goodsInfo.setGoodsId(CodeEnum.GOODS_INFO_CODE.getCode());
            // 设置商品规格
            if (goodsInfo.getIsBaseUnit()) {
                goodsInfo.setGoodsSpecs("kg");
            } else {
                BigDecimal conversionValue = goodsInfo.getConversionValue();
                if (conversionValue != null) {
                    String goodsSpecs = String.format("%skg/%s", conversionValue, getUnitName(goodsInfo.getGoodsUnitId()));
                    goodsInfo.setGoodsSpecs(goodsSpecs);
                }
            }
                goodsInfoMapper.insert(goodsInfo);
            } catch(Exception e){
                e.printStackTrace();
                throw exception(GOODS_INFO_FAIL_CREATE);
            }

            redisUtil.updateGoodsInfoRedis(goodsInfo.getId(), GoodsInfoConvert.INSTANCE.convertToDTO(goodsInfo));
            // 返回
            return goodsInfo.getId();
        }

    // 根据商品单位ID获取单位名称
    private String getUnitName(Long unitId) {
        UnitDO unit = unitMapper.selectById(unitId);
        if (unit != null) {
            return unit.getUnitName();
        } else {
            throw new RuntimeException("无法找到对应的单位");
        }
    }
    /**
     * 更新商品实现
     *
     * @param updateReqVO 更新信息
     */
    @Override
    public void updateGoodsInfo(GoodsInfoUpdateReqVO updateReqVO) {
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(updateReqVO.getBelongBusinessId());
        // 获取原始商品信息
        GoodsInfoDO originalGoodsInfo = goodsInfoMapper.selectById(updateReqVO.getId());
        if (originalGoodsInfo == null) {
            throw exception(GOODS_INFO_NOT_EXISTS);
        }
        //检查商品名称是否发生变化
        if (!Objects.equals(originalGoodsInfo.getGoodsName(),updateReqVO.getGoodsName())){
            //商品名称发生变化,进行唯一校验
            validateGoodsNameExists(updateReqVO.getGoodsName());
        }
        // 更新记录
        GoodsInfoDO newGoodsInfo = GoodsInfoConvert.INSTANCE.convert(updateReqVO);

        // 设置商品规格
        if (newGoodsInfo.getIsBaseUnit()) {
            newGoodsInfo.setGoodsSpecs("kg");
            newGoodsInfo.setGoodsUnitId(0L);
        } else {
            String goodsSpecs = String.format("%skg/%s", newGoodsInfo.getConversionValue(), getUnitName(newGoodsInfo.getGoodsUnitId()));
            newGoodsInfo.setGoodsSpecs(goodsSpecs);
        }
        try {
            goodsInfoMapper.updateById(newGoodsInfo);
        } catch (Exception e) {
            e.printStackTrace();
            throw exception(GOODS_INFO_FAIL_UPDATE);
        }

        redisUtil.updateGoodsInfoRedis(newGoodsInfo.getId(), GoodsInfoConvert.INSTANCE.convertToDTO(newGoodsInfo));
    }
    private void validateGoodsNameExists(String goodsName) {
        QueryWrapper<GoodsInfoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_name",goodsName);
        if (goodsInfoMapper.selectOne(wrapper) != null) {
            throw exception(GOODS_INFO_ALREADY_EXIST);
        }
    }
    /**
     * 删除商品实现
     *
     * @param id 编号
     */
    @Override
    @Transactional
    public void deleteGoodsInfo(Long id, String goodsId) {
        // 校验存在
        validateGoodsInfoExists(id);
        //校验是否存在关联采收批次
        if (!harvestBatchApi.getHarvestInfoListByGoodsId(goodsInfoMapper.selectById(id).getGoodsId()).getData().isEmpty()) {
            throw exception(GOODS_INFO_FAIL_DEL_BELONG_HARVEST_BATCH_EXISTS);
        }
        // 删除

        if (dealerGoodsMapper.selectList(DealerGoodsDO::getDealerId, goodsId).isEmpty()) {
            dealerGoodsMapper.delete(new QueryWrapperX<DealerGoodsDO>().eq("goods_id", goodsId));
        }
        goodsInfoMapper.deleteById(id);

        redisUtil.delGoodsInfoRedis(id);
    }

    private void validateGoodsInfoExists(Long id) {
        if (goodsInfoMapper.selectById(id) == null) {
            throw exception(ErrorCodeConstants.GOODS_INFO_NOT_EXISTS);
        }
    }

    /**
     * 获得商品实现
     *
     * @param id 编号
     * @return 商品
     */
    @Override
    public GoodsInfoDO getGoodsInfo(Long id) {
        return goodsInfoMapper.selectById(id);
    }


    /**
     * 获得商品列表
     *
     * @param goodsInfoListReqVO 根据信息内容动态查询
     * @return 商品列表
     */
    @Override
    public List<GoodsInfoDO> getGoodsInfoListQuery(GoodsInfoListReqVO goodsInfoListReqVO) {
        return goodsInfoMapper.selectListQuery(goodsInfoListReqVO);
    }

    /**
     * 获得商品分页实现
     *
     * @param pageReqVO 分页查询
     * @return 商品分页
     */
    @Override
    public PageResult<GoodsInfoDO> getGoodsInfoPage(GoodsInfoPageReqVO pageReqVO) {
        Page<GoodsInfoDO> page = new Page<>(pageReqVO.getPageNo(),pageReqVO.getPageSize());
        IPage<GoodsInfoDO> goodsInfoDOIPage = goodsInfoMapper.selectGoodsInfoById(page, pageReqVO.getGoodsName(),
                pageReqVO.getGoodsId(), pageReqVO.getGoodsUnitId(),pageReqVO.getBelongBusinessName());
        // 根据goodsUnitId设置goodsUnitName
        List<GoodsInfoDO> records = goodsInfoDOIPage.getRecords();
        for (GoodsInfoDO goodsInfo : records) {
            if (goodsInfo.getGoodsUnitId() == 0) {
                goodsInfo.setGoodsUnitName("kg");
            } else {
                goodsInfo.setGoodsUnitName(getUnitName(goodsInfo.getGoodsUnitId()));
            }
        }
        PageResult<GoodsInfoDO> goodsInfoDOPageResult = new PageResult<GoodsInfoDO>().setList(records);
        goodsInfoDOPageResult.setTotal(goodsInfoDOIPage.getTotal());
        return goodsInfoDOPageResult;
    }

    /**
     * 获取所有商品,利于前端客群洞察模块接口调用
     *
     * @return
     */
    @Override
    public List<GoodsInfoDO> getGoodsNameList() {
        //查询所有商品
        LambdaQueryWrapper<GoodsInfoDO> wrapper = new LambdaQueryWrapper<>();
        return goodsInfoMapper.selectList(wrapper);
    }

    /**
     * 根据指定的商户id 获取所有名下多个商品
     *
     * @param ids
     * @return 商品列表
     */
    @Override
    public List<GoodsInfoDO> getGoodsNameListByBusinessInfoId(List<Long> ids) {
        //查询所有商品
        LambdaQueryWrapper<GoodsInfoDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(GoodsInfoDO::getBelongBusinessId, ids);
        return goodsInfoMapper.selectList(wrapper);
    }

    /**
     * 根据商品编码列表获取商品列表
     *
     * @param goodsIds
     * @return 商品信息集合
     */
    @Override
    public List<GoodsInfoDO> getGoodsInfoListByGoodsIds(List<String> goodsIds, Long businessInfoId) {
        return goodsInfoMapper.selectList(new LambdaQueryWrapperX<GoodsInfoDO>().in(GoodsInfoDO::getGoodsId, goodsIds).eqIfPresent(GoodsInfoDO::getBelongBusinessId, businessInfoId));
    }

    /**
     * 根据指定的商户id 获取所有名下多个商品
     *
     * @param belongBusinessId 商户id列表
     * @return 商品列表
     */
    @Override
    public List<GoodsInfoDO> getGoodsListByBelongBusinessId(List<Long> belongBusinessId) {
        // 查询所有商品
        LambdaQueryWrapper<GoodsInfoDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(GoodsInfoDO::getBelongBusinessId, belongBusinessId);
        return goodsInfoMapper.selectList(wrapper);
    }

    @Override
    public List<GoodsInfoRespVO> getGoodsListByBusinessInfoId(Long businessInfoId) {
        return goodsInfoMapper.getGoodsListByBusinessInfoId(businessInfoId);
    }

    /**
     * 根据商户ID获得商品列表
     *
     * @param belongBusinessId 商户ID
     * @return 投入品
     */
    @Override
    public List<GoodsInfoForTransferRespVO> queryListMiniResult(Long belongBusinessId) {
        return goodsInfoMapper.queryListOfMiniResult(belongBusinessId);
    }

    @Override
    public GoodsInfoRespVO getByGoodsId(String goodsId) {
        return goodsInfoMapper.getByGoodsId(goodsId);
    }

}
