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

import cn.iocoder.yudao.framework.common.enums.CodeEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
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.dealerinfo.vo.DealerInfoCreateReqVO;
import cn.iocoder.yudao.module.basic.controller.admin.dealerinfo.vo.DealerInfoPageReqVO;
import cn.iocoder.yudao.module.basic.controller.admin.dealerinfo.vo.DealerInfoUpdateReqVO;
import cn.iocoder.yudao.module.basic.convert.dealerinfo.DealerInfoConvert;
import cn.iocoder.yudao.module.basic.dal.dataobject.dealergoods.DealerGoodsDO;
import cn.iocoder.yudao.module.basic.dal.dataobject.dealerinfo.DealerInfoDO;
import cn.iocoder.yudao.module.basic.dal.dataobject.goodsinfo.GoodsInfoDO;
import cn.iocoder.yudao.module.basic.dal.mysql.dealergoods.DealerGoodsMapper;
import cn.iocoder.yudao.module.basic.dal.mysql.dealerinfo.DealerInfoMapper;
import cn.iocoder.yudao.module.basic.dal.mysql.goodsinfo.GoodsInfoMapper;
import cn.iocoder.yudao.module.basic.service.businessinfo.BusinessInfoServiceImpl;
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.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
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 DealerInfoServiceImpl implements DealerInfoService {

    @Resource
    private DealerInfoMapper dealerInfoMapper;
    @Resource
    private DealerGoodsMapper dealerGoodsMapper;
    @Resource
    private GoodsInfoMapper goodsInfoMapper;
    @Resource
    private BusinessInfoServiceImpl businessInfoService;
    @Resource
    private RedisBasicInfoUtilApi redisUtil;

    @Override
    public Long createDealerInfo(DealerInfoCreateReqVO createReqVO) {
        // 校验存在
        validateDealerNameInfoExists(createReqVO.getDealerName(), (long) 0);
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(createReqVO.getBelongBusinessId());

        DealerInfoDO dealerInfo = DealerInfoConvert.INSTANCE.convert(createReqVO);
        // 插入
        try {
            dealerInfo.setDealerId(CodeEnum.DEALER_INFO_CODE.getCode());
            dealerInfoMapper.insert(dealerInfo);
        } catch (Exception e) {
            e.printStackTrace();
            throw exception(DEALER_GOODS_SQL_FAIL_CREATE);
        }
        redisUtil.updateDealerInfoRedis(dealerInfo.getId(), DealerInfoConvert.INSTANCE.convertToDealerInfoDTO(dealerInfo));
        // 返回
        return dealerInfo.getId();
    }

    //创建经销商和经销商商品
    @Override
    @Transactional
    public Long createDealerGoodsInfo(DealerInfoCreateReqVO createDealerInfo, List<DealerGoodsDO> areaGoodsList) {
        // 校验存在
        validateDealerNameInfoExists(createDealerInfo.getDealerName(), (long) 0);
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(createDealerInfo.getBelongBusinessId());

        // 插入
        DealerInfoDO dealerInfo = DealerInfoConvert.INSTANCE.convert(createDealerInfo);
        dealerInfo.setDealerId(CodeEnum.DEALER_INFO_CODE.getCode());
        if (areaGoodsList.size() > 0) {
            //校验选择商品是否存在
            List<GoodsInfoDO> goodsInfoDoList = goodsInfoMapper.selectList(new LambdaQueryWrapperX<GoodsInfoDO>().select(GoodsInfoDO::getGoodsId));
            List<String> notExistGoods = new ArrayList<>();
            String errorInfo = null;
            areaGoodsList.forEach(item -> {
                if (!"未选择".equals(item.getGoodsId())) {
                    long count = goodsInfoDoList.stream().filter(goodsInfoDo -> goodsInfoDo.getGoodsId().equals(item.getGoodsId()))
                            .count();
                    if (count == 0) {
                        notExistGoods.add(item.getGoodsName());
                    }
                }
            });
            for (int i = 0; i < notExistGoods.size(); i++) {
                if (i == 0) {
                    errorInfo = notExistGoods.get(i);
                } else {
                    errorInfo = errorInfo + '/' + notExistGoods.get(i);
                }
            }
            if (notExistGoods.size() != 0) {
                ErrorCode SELECT_GOODS_INFO_NOT_EXISTS = new ErrorCode(1010005000, "商品不存在：" + errorInfo);
                throw exception(SELECT_GOODS_INFO_NOT_EXISTS);
            }

            //过滤出DealerId为空的项，通过循环将DealerId填入
            areaGoodsList.stream().filter(item -> StringUtils.isEmpty(item.getDealerId()))
                    .forEach(item2 -> item2.setDealerId(dealerInfo.getDealerId()));
        }
        //校验相同地区是否存在相同商品
        validateDealerSameGoodsExists(areaGoodsList, null);

        dealerInfoMapper.insert(dealerInfo);
        dealerGoodsMapper.insertBatch(areaGoodsList);

        redisUtil.updateDealerInfoRedis(dealerInfo.getId(), DealerInfoConvert.INSTANCE.convertToDealerInfoDTO(dealerInfo));
        // 返回
        return dealerInfo.getId();
    }

    @Override
    public void updateDealerInfo(DealerInfoUpdateReqVO updateReqVO) {
        // 校验存在
        validateDealerInfoExists(updateReqVO.getId());
        validateDealerNameInfoExists(updateReqVO.getDealerName(), updateReqVO.getId());
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(updateReqVO.getBelongBusinessId());

        // 更新
        DealerInfoDO updateObj = DealerInfoConvert.INSTANCE.convert(updateReqVO);
        try {
            dealerInfoMapper.updateById(updateObj);
        } catch (Exception e) {
            e.printStackTrace();
            throw exception(DEALER_GOODS_SQL_FAIL_UPDATE);
        }

        redisUtil.updateDealerInfoRedis(updateObj.getId(), DealerInfoConvert.INSTANCE.convertToDealerInfoDTO(updateObj));
    }


    //更新经销商和经销商商品
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public void updateDealerAndAreaGoodsInfo(DealerInfoUpdateReqVO updateDealerInfo, List<DealerGoodsDO> areaGoodsAddList
            , List<DealerGoodsDO> areaGoodsUpdateList) {
        // 校验存在
        validateDealerInfoExists(updateDealerInfo.getId());
        validateDealerNameInfoExists(updateDealerInfo.getDealerName(), updateDealerInfo.getId());
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(updateDealerInfo.getBelongBusinessId());

        // 更新
        DealerInfoDO updateObj = DealerInfoConvert.INSTANCE.convert(updateDealerInfo);

        if (!areaGoodsAddList.isEmpty()) {
            //校验相同地区是否存在相同商品
            validateDealerSameGoodsExists(areaGoodsAddList, updateObj.getDealerId());
        }
        if (!areaGoodsUpdateList.isEmpty()) {
            //校验相同地区是否存在相同商品
            validateDealerSameGoodsExists(areaGoodsUpdateList, updateObj.getDealerId());
        }

        //存放不存在的商品
        List<String> notExistAddGoods = new ArrayList<>();
        List<String> notExistUpdateGoods = new ArrayList<>();

        try {
            if (!areaGoodsAddList.isEmpty() || !areaGoodsUpdateList.isEmpty()) {
                List<GoodsInfoDO> goodsInfoDoList = goodsInfoMapper.selectList(new LambdaQueryWrapperX<GoodsInfoDO>()
                        .select(GoodsInfoDO::getGoodsId));
                if (!areaGoodsAddList.isEmpty()) {
                    //校验选择商品是否存在
                    areaGoodsAddList.forEach(item -> {
                        if (!"未选择".equals(item.getGoodsId())) {
                            long count = goodsInfoDoList.stream().filter(goodsInfoDo -> goodsInfoDo.getGoodsId().equals(item.getGoodsId()))
                                    .count();
                            if (count == 0) {
                                notExistAddGoods.add(item.getGoodsName());
                            }
                        }
                    });
                    if (notExistAddGoods.size() == 0) {
                        dealerGoodsMapper.insertBatch(areaGoodsAddList);
                    }
                }
                if (!areaGoodsUpdateList.isEmpty()) {
                    //校验选择商品是否存在
                    areaGoodsUpdateList.forEach(item -> {
                        if (!"未选择".equals(item.getGoodsId())) {
                            long count = goodsInfoDoList.stream().filter(goodsInfoDo -> goodsInfoDo.getGoodsId().equals(item.getGoodsId()))
                                    .count();
                            if (count == 0) {
                                notExistUpdateGoods.add(item.getGoodsName());
                            }
                        }
                    });
                    if (notExistUpdateGoods.size() == 0) {
                        dealerGoodsMapper.updateBatch(areaGoodsUpdateList, areaGoodsUpdateList.size());
                    }
                }
                if (notExistAddGoods.size() != 0 || notExistUpdateGoods.size() != 0) {
                    throw exception(GOODS_INFO_NOT_EXISTS);
                }
            }
            dealerInfoMapper.updateById(updateObj);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            if (notExistAddGoods.size() != 0 || notExistUpdateGoods.size() != 0) {
                String errorAddInfo = "无";
                String erroUpdateInfo = "无";
                if (notExistAddGoods.size() != 0) {
                    for (int i = 0; i < notExistAddGoods.size(); i++) {
                        if (i == 0) {
                            errorAddInfo = notExistAddGoods.get(i);
                        } else {
                            errorAddInfo = errorAddInfo + '/' + notExistAddGoods.get(i);
                        }
                    }
                }
                if (notExistUpdateGoods.size() != 0) {
                    for (int i = 0; i < notExistUpdateGoods.size(); i++) {
                        if (i == 0) {
                            erroUpdateInfo = notExistUpdateGoods.get(i);
                        } else {
                            erroUpdateInfo = erroUpdateInfo + '/' + notExistUpdateGoods.get(i);
                        }
                    }
                }
                ErrorCode SELECT_GOODS_INFO_NOT_EXISTS = new ErrorCode(1010005000,
                        "新增商品不存在：" + errorAddInfo + "，" + "更新商品不存在：" + erroUpdateInfo);
                throw exception(SELECT_GOODS_INFO_NOT_EXISTS);
            } else {
                throw exception(DEALER_GOODS_SQL_FAIL_UPDATE);
            }
        }

        redisUtil.updateDealerInfoRedis(updateObj.getId(), DealerInfoConvert.INSTANCE.convertToDealerInfoDTO(updateObj));
    }

    @Override
    public void deleteDealerInfo(Long id) {
        // 校验存在
        validateDealerInfoExists(id);
        // 删除
        dealerInfoMapper.deleteById(id);
    }

    /**
     * 删除经销商
     *
     * @param id 编号
     */
    @Override
    @Transactional
    public void deleteDealerAndAreaGoodsInfo(Long id) {
        // 校验存在
        validateDealerInfoExists(id);
        // 删除
        String dealer_id = dealerInfoMapper.selectById(id).getDealerId();
        QueryWrapper<DealerGoodsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("dealer_id", dealer_id);
        dealerInfoMapper.deleteById(id);
        dealerGoodsMapper.delete(wrapper);

        redisUtil.delDealerInfoRedis(id);
    }


    private void validateDealerInfoExists(Long id) {
        if (dealerInfoMapper.selectById(id) == null) {
            throw exception(DEALER_INFO_NOT_EXISTS);
        }
    }

    private void validateDealerNameInfoExists(String dealerName, Long id) {
        QueryWrapper<DealerInfoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("dealer_name", dealerName);
        wrapper.ne("id", id);
        if (dealerInfoMapper.selectOne(wrapper) != null) {
            throw exception(DEALER_INFO_IS_EXISTS_DEALER_NAME);
        }
    }

    @Override
    public DealerInfoDO getDealerInfo(Long id) {
        return dealerInfoMapper.selectById(id);
    }

    @Override
    public PageResult<DealerInfoDO> getDealerInfoPage(DealerInfoPageReqVO pageReqVO) {
        PageResult<DealerInfoDO> dealerInfoDOPageResult = new PageResult<>();

        if (pageReqVO.getBelongBusinessName() != null && !Objects.equals(pageReqVO.getBelongBusinessName(), "")) {
            Page<DealerInfoDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
            IPage<DealerInfoDO> dealerInfoDOIPage = dealerInfoMapper.selectPageByInfo(page, new QueryWrapperX<DealerInfoDO>()
                    .eqIfPresent("dealer_id", pageReqVO.getDealerId())
                    .likeIfPresent("dealer_name", pageReqVO.getDealerName())
                    .likeIfPresent("bbi.business_name", pageReqVO.getBelongBusinessName())
                    .eqIfPresent("contact_phone", pageReqVO.getContactPhone())
                    .likeIfPresent("contact_name", pageReqVO.getContactName())
                    .betweenIfPresent("create_time", pageReqVO.getCreateTime())
                    .eq("bdi.deleted", 0));

            dealerInfoDOPageResult.setList(dealerInfoDOIPage.getRecords());
            dealerInfoDOPageResult.setTotal(dealerInfoDOIPage.getTotal());
        } else {
            dealerInfoDOPageResult = dealerInfoMapper.selectPage(pageReqVO);
        }
        dealerInfoDOPageResult.getList().forEach(item -> {
            if (redisUtil.validateBusinessInfoRedisExists(item.getBelongBusinessId())) {
                item.setBelongBusinessName(redisUtil.getBusinessInfoRedis(item.getBelongBusinessId()).getBusinessName());
            } else {
                item.setBelongBusinessName("所属商户不存在");
            }
        });
        return dealerInfoDOPageResult;
    }

    /**
     * 查询所有经销商昵称
     *
     * @return
     */
    @Override
    public List<DealerInfoDO> getPullInfoList() {
        //查询所有经销商
        LambdaQueryWrapper<DealerInfoDO> wrapper = new LambdaQueryWrapper<>();
        return dealerInfoMapper.selectList(wrapper);
    }

    /**
     * 根据经销商编码获取经销商信息
     *
     * @param dealerId
     * @return
     */
    @Override
    public DealerInfoDO getDealerGoodsInfoByDealerGoodsId(String dealerId) {
        DealerInfoDO dealerInfoDO = new DealerInfoDO();
        dealerInfoDO.setDealerId(dealerId);
        return dealerInfoMapper.selectOne(new QueryWrapper<>(dealerInfoDO));
    }

    @Override
    public DealerInfoDO getDealerInfoByGoods(String dealerId, Long businessInfoId, String goodsId) {
        return dealerInfoMapper.getDealerInfoByGoods(dealerId, businessInfoId, goodsId).get(0);
    }

    @Override
    public List<DealerInfoDO> getDealerInfoByGoodsId(String goodsId, Long businessInfoId) {
        return dealerInfoMapper.getDealerInfoByGoods(null, businessInfoId, goodsId);
    }

    //校验相同地区是否存在相同商品
    private void validateDealerSameGoodsExists(List<DealerGoodsDO> areaGoodsList, String dealerId) {
        for (int i = 0; i < areaGoodsList.size(); i++) {
            DealerGoodsDO areaGoods = areaGoodsList.get(i);
            if (areaGoods.getGoodsId().equals("未选择")) {
                continue;
            }
            for (int j = 0; j < areaGoodsList.size(); j++) {
                if (i != j) {
                    DealerGoodsDO areaGoodsJ = areaGoodsList.get(j);
                    if (!areaGoodsJ.getGoodsId().equals("未选择")
                            && areaGoodsJ.getSaleArea().equals(areaGoods.getSaleArea())
                            && areaGoodsJ.getGoodsId().equals(areaGoods.getGoodsId())) {
                        throw exception(SAME_DEALER_GOODS_EXISTS_IN_THE_AREA);
                    }
                }
            }
        }

        if (dealerId != null) {
            List<DealerGoodsDO> getAreaGoodsList = dealerGoodsMapper.selectList(
                    new LambdaQueryWrapperX<DealerGoodsDO>().eq(DealerGoodsDO::getDealerId, dealerId)
            );
            areaGoodsList.stream().forEach(areaGoods -> {
                if (areaGoods.getGoodsId().equals("未选择")) {
                    return;
                }
                getAreaGoodsList.stream().forEach(item -> {
                    if (!item.getGoodsId().equals("未选择")
                            && item.getSaleArea().equals(areaGoods.getSaleArea())
                            && item.getGoodsId().equals(areaGoods.getGoodsId())
                            && !item.getId().equals(areaGoods.getId())) {
                        throw exception(SAME_DEALER_GOODS_EXISTS_IN_THE_AREA);
                    }
                });
            });
        }
    }

}
