
package com.tmerclub.cloud.distribution.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.distribution.vo.DistributionSpuVO;
import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.constant.ShopStatus;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.platform.constant.OfflineHandleEventStatus;
import com.tmerclub.cloud.api.platform.constant.OfflineHandleEventType;
import com.tmerclub.cloud.api.platform.dto.OfflineHandleEventDTO;
import com.tmerclub.cloud.api.platform.feign.OfflineHandleEventFeignClient;
import com.tmerclub.cloud.api.platform.vo.OfflineHandleEventVO;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.product.vo.SpuVO;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.Arith;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.distribution.constant.AwardMode;
import com.tmerclub.cloud.distribution.constant.DistributionSpuStatus;
import com.tmerclub.cloud.distribution.constant.ParentAwardSet;
import com.tmerclub.cloud.distribution.dto.DistributionSpuDTO;
import com.tmerclub.cloud.distribution.mapper.DistributionSpuMapper;
import com.tmerclub.cloud.distribution.model.DistributionSpu;
import com.tmerclub.cloud.distribution.service.DistributionSpuService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 分销商品关联信息
 *
 * @author cl
 * @date 2021-08-09 14:14:07
 */
@Service
public class DistributionSpuServiceImpl implements DistributionSpuService {

    @Autowired
    private DistributionSpuMapper distributionSpuMapper;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @DubboReference
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;

    /**
     * 比例最大存储值
     */
    private static final Long PROPORTION_MAX_STORAGE_VALUE = 10000L;

    @Override
    public DistributionSpuVO getByDistributionSpuId(Long distributionSpuId) {
        DistributionSpuVO distributionSpuVO = distributionSpuMapper.getByDistributionSpuId(distributionSpuId);
        ServerResponseEntity<SpuVO> spuRes = spuFeignClient.getDetailById(distributionSpuVO.getSpuId());
        if (!spuRes.isSuccess()) {
            throw new LuckException(spuRes.getMsg());
        }
        distributionSpuVO.setSpuName(spuRes.getData().getName());
        distributionSpuVO.setMainImgUrl(spuRes.getData().getMainImgUrl());
        return distributionSpuVO;
    }

    @Override
    public void save(DistributionSpuDTO distributionSpuDTO) {
        this.validateDistributionSpu(distributionSpuDTO, true);
        DistributionSpu distributionSpu = BeanUtil.map(distributionSpuDTO, DistributionSpu.class);
        // 检查商品是否存在
        checkSpu(distributionSpu);
        distributionSpuMapper.save(distributionSpu);
    }

    /**
     * 检查商品是否存在
     *
     * @param distributionSpu
     */
    private void checkSpu(DistributionSpu distributionSpu) {
        SpuVO spuVO = spuFeignClient.getById(distributionSpu.getSpuId()).getData();
        // 商品状态 1上架
        Integer status = 1;
        if (!Objects.equals(spuVO.getStatus(), status)) {
            throw new LuckException("商品已不存在，请刷新页面");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DistributionSpuDTO distributionSpuDTO) {
        DistributionSpuVO byDistributionSpuId = distributionSpuMapper.getByDistributionSpuId(distributionSpuDTO.getDistributionSpuId());
        if (Objects.isNull(byDistributionSpuId)) {
            throw new LuckException("分销商品已不存在，请刷新页面");
        }
        this.validateDistributionSpu(distributionSpuDTO, false);
        DistributionSpu distributionSpu = BeanUtil.map(distributionSpuDTO, DistributionSpu.class);
        if (!Objects.equals(byDistributionSpuId.getSpuId(), distributionSpuDTO.getSpuId())) {
            distributionSpuMapper.deleteById(byDistributionSpuId.getDistributionSpuId());
            distributionSpu.setDistributionSpuId(byDistributionSpuId.getDistributionSpuId());
            distributionSpu.setState(byDistributionSpuId.getState());
            distributionSpuMapper.save(distributionSpu);
        } else {
            distributionSpuMapper.update(distributionSpu);
        }
    }

    @Override
    public void deleteById(Long distributionSpuId) {
        distributionSpuMapper.deleteById(distributionSpuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByIdAndShopId(Long distributionSpuId, Long shopId) {
        // 删除分销信息
        distributionSpuMapper.deleteByIdAndShopId(distributionSpuId, shopId);
        // 删除分销审核信息
        ServerResponseEntity<Void> offlineDeleteRes = offlineHandleEventFeignClient.deleteByHandleTypeAndHandleId(OfflineHandleEventType.DISTRIBUTION_PROD.getValue(), distributionSpuId);
        if (!offlineDeleteRes.isSuccess()) {
            throw new LuckException(offlineDeleteRes.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void offline(OfflineHandleEventDTO offlineHandleEventDTO) {
        DistributionSpuVO distributionSpuVO = distributionSpuMapper.getByDistributionSpuId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(distributionSpuVO)) {
            throw new LuckException("分销商品不存在，请刷新页面");
        }
        if (Objects.equals(distributionSpuVO.getState(), DistributionSpuStatus.PLATFORM_OFF_SHELF.value())) {
            throw new LuckException("该分销商品已下线，请刷新页面");
        }
        OfflineHandleEventDTO offlineHandleEvent = new OfflineHandleEventDTO();
        offlineHandleEvent.setHandleId(offlineHandleEventDTO.getHandleId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.DISTRIBUTION_PROD.getValue());
        offlineHandleEvent.setOfflineReason(offlineHandleEventDTO.getOfflineReason());
        ServerResponseEntity<Void> offlineRes = offlineHandleEventFeignClient.save(offlineHandleEvent);
        if (!offlineRes.isSuccess()) {
            throw new LuckException(offlineRes.getMsg());
        }
        // 更新分销商品状态为下线状态
        int changeCount = distributionSpuMapper.changeStateByDistributionId(offlineHandleEventDTO.getHandleId(), distributionSpuVO.getState(), DistributionSpuStatus.PLATFORM_OFF_SHELF.value());
        if (changeCount != 1) {
            throw new LuckException("下线失败，请刷新页面后重试");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void auditApply(OfflineHandleEventDTO offlineHandleEventDTO) {
        DistributionSpuVO distributionSpuVO = distributionSpuMapper.getByDistributionSpuId(offlineHandleEventDTO.getHandleId());
        if (!Objects.equals(AuthUserContext.get().getTenantId(), Constant.PLATFORM_SHOP_ID) && !Objects.equals(AuthUserContext.get().getTenantId(), distributionSpuVO.getShopId())) {
            throw new LuckException("该分销商品不属于当前店铺");
        }
        if (!Objects.equals(distributionSpuVO.getState(), DistributionSpuStatus.PLATFORM_OFF_SHELF.value())) {
            throw new LuckException("该分销商品状态已经发生变化，请刷新页面");
        }
        // 更新事件状态
        ServerResponseEntity<Void> offlineRes = offlineHandleEventFeignClient.updateToApply(offlineHandleEventDTO);
        if (!offlineRes.isSuccess()) {
            throw new LuckException(offlineRes.getMsg());
        }
        // 更新分销商品状态
        int changeCount = distributionSpuMapper.changeStateByDistributionId(offlineHandleEventDTO.getHandleId(), distributionSpuVO.getState(), DistributionSpuStatus.WAITAUDIT.value());
        if (changeCount != 1) {
            throw new LuckException("申请失败，请刷新页面后重试");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void audit(OfflineHandleEventDTO offlineHandleEventDTO) {
        DistributionSpuVO distributionSpuVO = distributionSpuMapper.getByDistributionSpuId(offlineHandleEventDTO.getHandleId());
        if (!Objects.equals(distributionSpuVO.getState(), DistributionSpuStatus.WAITAUDIT.value())) {
            throw new LuckException("该分销商品已经审核");
        }
        ServerResponseEntity<Void> offlineRes = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDTO);
        if (!offlineRes.isSuccess()) {
            throw new LuckException(offlineRes.getMsg());
        }
        Integer newState = 0;
        // 审核通过
        if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            newState = DistributionSpuStatus.PUT_SHELF.value();
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            newState = DistributionSpuStatus.PLATFORM_OFF_SHELF.value();
        }
        int changeCount = distributionSpuMapper.changeStateByDistributionId(offlineHandleEventDTO.getHandleId(), distributionSpuVO.getState(), newState);
        if (changeCount != 1) {
            throw new LuckException("审核失败，请刷新页面后重试");
        }
    }

    @Override
    public DistributionSpuVO getBySpuId(Long spuId) {
        return distributionSpuMapper.getBySpuId(spuId);
    }


    @Override
    public OfflineHandleEventVO getOfflineHandleEvent(Long distributionSpuId) {
        ServerResponseEntity<OfflineHandleEventVO> offlineRes = offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.DISTRIBUTION_PROD.getValue(), distributionSpuId, null);
        if (!offlineRes.isSuccess()) {
            throw new LuckException(offlineRes.getMsg());
        }
        return offlineRes.getData();
    }

    @Override
    public void updateState(Long distributionSpuId, Integer state) {
        DistributionSpuVO distributionSpuVO = distributionSpuMapper.getByDistributionSpuId(distributionSpuId);
        if (Objects.isNull(distributionSpuVO)) {
            throw new LuckException("分销商品不存在，请刷新页面");
        }
        //校验
        validateDistributionUpdateState(distributionSpuVO);
        if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.MULTISHOP.value())) {
            // 商家端操作
            if (Objects.equals(distributionSpuVO.getState(), DistributionSpuStatus.PLATFORM_OFF_SHELF.value()) || Objects.equals(distributionSpuVO.getState(), DistributionSpuStatus.WAITAUDIT.value())) {
                throw new LuckException("当前分销商品状态无法更改");
            }
        }
        int changeCount = distributionSpuMapper.changeStateByDistributionId(distributionSpuId, distributionSpuVO.getState(), state);
        if (changeCount != 1) {
            throw new LuckException("状态变更失败，请刷新后重试");
        }
    }

    @Override
    public Boolean isStateBySpuIdAndState(Long spuId, Integer state) {
        int count = distributionSpuMapper.countBySpuIdAndState(spuId, state);
        return count > 0;
    }

    @Override
    public List<DistributionSpu> getByStateAndSpuIds(Integer state, List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return null;
        }
        return distributionSpuMapper.getByStateAndSpuIds(state, spuIds);
    }

    @Override
    public void handleSpuState(List<Long> spuIds, List<Long> shopIds, Integer state) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        List<DistributionSpu> distributionSpuList = distributionSpuMapper.getDistributionSpuListBySpuIdsAndShopIds(spuIds, shopIds);
        List<Long> changeSpuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 同步商品状态
        if (Objects.equals(state, StatusEnum.ENABLE.value())) {
            // 上架
            distributionSpuList.forEach(distributionSpu -> {
                if (Objects.equals(distributionSpu.getState(), StatusEnum.DISABLE.value())) {
                    changeSpuIds.add(distributionSpu.getSpuId());
                }
            });
        } else if (Objects.equals(state, StatusEnum.DISABLE.value()) || Objects.equals(state, StatusEnum.OFFLINE.value())) {
            // 商家下架或平台违规下架
            distributionSpuList.forEach(distributionSpu -> {
                if (Objects.equals(distributionSpu.getState(), StatusEnum.ENABLE.value())) {
                    changeSpuIds.add(distributionSpu.getSpuId());
                }
            });
            state = StatusEnum.DISABLE.value();
        }
        if (CollUtil.isNotEmpty(changeSpuIds)) {
            distributionSpuMapper.updateState(changeSpuIds, state);
        }
    }

    /**
     * 校验分销商品信息
     *
     * @param distributionSpuDTO 分销商品信息
     * @param createOrUpdate     true: 创建时校验    false: 更新时校验
     */
    private void validateDistributionSpu(DistributionSpuDTO distributionSpuDTO, boolean createOrUpdate) {
        // 根据商品id查询分销信息
        DistributionSpuVO distributionSpuVO = distributionSpuMapper.getBySpuId(distributionSpuDTO.getSpuId());
        // 判断分销信息是否已经存在
        if (createOrUpdate) {
            if (Objects.nonNull(distributionSpuVO)) {
                throw new LuckException("该商品已经添加到分销商品，不能重复添加");
            }
        }
        ServerResponseEntity<SpuVO> spuRes = spuFeignClient.getDetailById(distributionSpuDTO.getSpuId());
        if (!spuRes.isSuccess()) {
            throw new LuckException(spuRes.getMsg());
        }
        SpuVO spuVO = spuRes.getData();
        if (Objects.isNull(spuVO)) {
            throw new LuckException("选择的商品不存在，请刷新后重试");
        }
        // 判断当前商品是否属于该店铺
        if (!Objects.equals(spuVO.getShopId(), distributionSpuDTO.getShopId())) {
            throw new LuckException("当前商品不属于你的店铺");
        }
        // 按比例
        if (Objects.equals(distributionSpuDTO.getAwardMode(), AwardMode.PROPORTION.value())) {
            // 校验直推奖励
            if (distributionSpuDTO.getAwardNumbers() >= PROPORTION_MAX_STORAGE_VALUE) {
                throw new LuckException("直推奖励比例最大不能超过" + (PROPORTION_MAX_STORAGE_VALUE / 100) + "%");
            }
            if (Objects.equals(distributionSpuDTO.getParentAwardSet(), ParentAwardSet.OPEN.value())) {
                // 校验间推奖励
                if (distributionSpuDTO.getParentAwardNumbers() >= PROPORTION_MAX_STORAGE_VALUE) {
                    throw new LuckException("间推奖励比例最大不能超过" + (PROPORTION_MAX_STORAGE_VALUE / 100) + "%");
                }
                if (Arith.add(distributionSpuDTO.getAwardNumbers(), distributionSpuDTO.getParentAwardNumbers()) >= PROPORTION_MAX_STORAGE_VALUE) {
                    throw new LuckException("直推与间推奖励比例之和最大不能超过" + (PROPORTION_MAX_STORAGE_VALUE / 100) + "%");
                }
            }
        } else {
            // 按实际金额
            // 校验直推奖励
            if (distributionSpuDTO.getAwardNumbers() >= spuVO.getPriceFee()) {
                throw new LuckException("直推奖励固定奖励不能超过商品原价格");
            }
            if (Objects.equals(distributionSpuDTO.getParentAwardSet(), ParentAwardSet.OPEN.value())) {
                // 校验间推奖励
                if (distributionSpuDTO.getParentAwardNumbers() >= spuVO.getPriceFee()) {
                    throw new LuckException("间推奖励固定奖励不能超过商品原价格");
                }
                if (Arith.add(distributionSpuDTO.getAwardNumbers(), distributionSpuDTO.getParentAwardNumbers()) >= spuVO.getPriceFee()) {
                    throw new LuckException("直推与间推奖励之和最大不能超过商品原价");
                }
            }
        }
    }

    /**
     * 上下架条件校验
     *
     * @param distributionSpuVO
     */
    private void validateDistributionUpdateState(DistributionSpuVO distributionSpuVO) {
        ServerResponseEntity<SpuVO> spuRes = spuFeignClient.getDetailById(distributionSpuVO.getSpuId());
        if (!spuRes.isSuccess()) {
            throw new LuckException(spuRes.getMsg());
        }
        SpuVO spuVO = spuRes.getData();
        if (Objects.isNull(spuVO)) {
            throw new LuckException("商品不存在，请刷新后重试");
        }
        Long shopId = AuthUserContext.get().getTenantId();
        if (!Objects.equals(spuVO.getShopId(), shopId)) {
            throw new LuckException("当前商品不属于你的店铺");
        }
        ServerResponseEntity<EsShopDetailBO> shopByShopId = shopDetailFeignClient.getShopByShopId(shopId);
        if (!shopByShopId.isSuccess()) {
            throw new LuckException(shopByShopId.getMsg());
        }
        EsShopDetailBO shopDetail = shopByShopId.getData();
        //上架操作校验
        if (Objects.equals(distributionSpuVO.getState(), DistributionSpuStatus.OFF_SHELF.value())) {
            if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OPEN.value()) && !Objects.equals(shopDetail.getShopStatus(), ShopStatus.STOP.value())) {
                // 不能把分销商品更新为上架状态
                throw new LuckException("店铺处于违规下架状态，不能将分销商品置为上架状态");
            }
            if (!Objects.equals(spuVO.getStatus(), StatusEnum.ENABLE.value())) {
                // 商品不处于上线状态，分销商品不能进行上架操作
                throw new LuckException("商品不处于上线状态，分销商品不能进行上架操作");
            }
        }
    }
}
