package com.fzm.mall.server.admin.opration.service.impl;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fzm.mall.server.admin.constant.MallResponseError;
import com.fzm.mall.server.admin.exception.MyException;
import com.fzm.mall.server.admin.goods_center.entity.vo.GoodsListVO;
import com.fzm.mall.server.admin.goods_center.model.Category;
import com.fzm.mall.server.admin.goods_center.model.Spu;
import com.fzm.mall.server.admin.goods_center.service.ICategoryService;
import com.fzm.mall.server.admin.goods_center.service.ISpuService;
import com.fzm.mall.server.admin.opration.entity.dto.IntegralReturnMerchantDTO;
import com.fzm.mall.server.admin.opration.entity.dto.IntegralReturnMerchantEditDTO;
import com.fzm.mall.server.admin.opration.entity.vo.IntegralReturnMerchantDetailVO;
import com.fzm.mall.server.admin.opration.entity.vo.IntegralReturnMerchantVO;
import com.fzm.mall.server.admin.opration.enums.status.IntegralReturnMerchantStatusEnum;
import com.fzm.mall.server.admin.opration.enums.type.IntegralReturnGoodsRangeTypeEnum;
import com.fzm.mall.server.admin.opration.mapper.IntegralReturnMerchantMapper;
import com.fzm.mall.server.admin.opration.model.IntegralReturnCategory;
import com.fzm.mall.server.admin.opration.model.IntegralReturnMerchant;
import com.fzm.mall.server.admin.opration.model.IntegralReturnSpu;
import com.fzm.mall.server.admin.opration.service.IIntegralReturnCategoryService;
import com.fzm.mall.server.admin.opration.service.IIntegralReturnMerchantService;
import com.fzm.mall.server.admin.opration.service.IIntegralReturnSpuService;
import com.fzm.mall.server.admin.util.UUIDUtil;
import io.swagger.annotations.ApiModelProperty;
import org.dozer.DozerBeanMapper;
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.stream.Collectors;

/**
 * <p>
 * 积分返现——商户 服务实现类
 * </p>
 *
 * @author fzm
 * @since 2021-07-29
 */
@Service
@Transactional
public class IntegralReturnMerchantServiceImpl extends ServiceImpl<IntegralReturnMerchantMapper, IntegralReturnMerchant> implements IIntegralReturnMerchantService {

    @Autowired
    private DozerBeanMapper beanMapper;
    @Autowired
    private IIntegralReturnCategoryService integralReturnCategoryService;
    @Autowired
    private IIntegralReturnSpuService integralReturnSpuService;
    @Autowired
    private ICategoryService categoryService;
    @Autowired
    private ISpuService spuService;

    @Override
    public void add(IntegralReturnMerchantDTO dto, String merchantId) {
        String returnId = UUIDUtil.getUUID();

        //返现类目
        if (dto.getGoodsRange().equals(IntegralReturnGoodsRangeTypeEnum.APPOINT_CATEGORY.getType())) {
            List<IntegralReturnCategory> categories = dto.getCategoryList().stream().map(categoryDTO -> {
                IntegralReturnCategory category = new IntegralReturnCategory();
                category.setCategoryId(categoryDTO.getCategoryId());
                category.setReturnId(returnId);
                return category;
            }).collect(Collectors.toList());
            integralReturnCategoryService.saveBatch(categories);
        }

        //返现商品
        if (dto.getGoodsRange().equals(IntegralReturnGoodsRangeTypeEnum.APPOINT_GOODS.getType())) {
            List<IntegralReturnSpu> goods = dto.getGoodsList().stream().map(goodsId -> {
                IntegralReturnSpu spu = new IntegralReturnSpu();
                spu.setGoodsId(goodsId);
                spu.setReturnId(returnId);
                return spu;
            }).collect(Collectors.toList());
            integralReturnSpuService.saveBatch(goods);
        }

        IntegralReturnMerchant integralReturnMerchant = beanMapper.map(dto, IntegralReturnMerchant.class);
        integralReturnMerchant.setReturnId(returnId);
        integralReturnMerchant.setMerchantId(merchantId);
        Integer status;
        if (dto.getEffectiveStartTime() > System.currentTimeMillis()) {
            status = IntegralReturnMerchantStatusEnum.WAIT_START.getStatus();
        } else {
            status = IntegralReturnMerchantStatusEnum.ABLE.getStatus();
        }
        integralReturnMerchant.setStatus(status);
        save(integralReturnMerchant);
    }

    @Override
    public void edit(IntegralReturnMerchantEditDTO dto, String merchantId) {
        IntegralReturnMerchant returnMerchant = beanMapper.map(dto, IntegralReturnMerchant.class);
        LambdaUpdateWrapper<IntegralReturnMerchant> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IntegralReturnMerchant::getReturnId, dto.getReturnId())
                .eq(IntegralReturnMerchant::getUpdateTime, dto.getUpdateTime());
        boolean update = update(returnMerchant, updateWrapper);
        if (!update) {
            throw new MyException(MallResponseError.UPDATE_ERROR);
        }

        //返现类目
        if (dto.getGoodsRange().equals(IntegralReturnGoodsRangeTypeEnum.APPOINT_CATEGORY.getType())) {
            LambdaQueryWrapper<IntegralReturnCategory> qwCategory = new LambdaQueryWrapper<>();
            qwCategory.eq(IntegralReturnCategory::getReturnId, dto.getReturnId());
            integralReturnCategoryService.remove(qwCategory);

            List<IntegralReturnCategory> categories = dto.getCategoryList().stream().map(categoryDTO -> {
                IntegralReturnCategory category = new IntegralReturnCategory();
                category.setCategoryId(categoryDTO.getCategoryId());
                category.setReturnId(dto.getReturnId());
                return category;
            }).collect(Collectors.toList());
            integralReturnCategoryService.saveBatch(categories);
        }

        //返现商品
        if (dto.getGoodsRange().equals(IntegralReturnGoodsRangeTypeEnum.APPOINT_GOODS.getType())) {
            LambdaQueryWrapper<IntegralReturnSpu> qwSpu = new LambdaQueryWrapper<>();
            qwSpu.eq(IntegralReturnSpu::getReturnId, dto.getReturnId());
            integralReturnSpuService.remove(qwSpu);

            List<IntegralReturnSpu> goods = dto.getGoodsList().stream().map(goodsId -> {
                IntegralReturnSpu spu = new IntegralReturnSpu();
                spu.setGoodsId(goodsId);
                spu.setReturnId(dto.getReturnId());
                return spu;
            }).collect(Collectors.toList());
            integralReturnSpuService.saveBatch(goods);
        }

    }

    @Override
    public void delete(String returnId) {
        LambdaUpdateWrapper<IntegralReturnMerchant> uw = new LambdaUpdateWrapper<>();
        uw.set(IntegralReturnMerchant::getStatus, IntegralReturnMerchantStatusEnum.DELETE.getStatus());
        uw.eq(IntegralReturnMerchant::getReturnId, returnId);
        update(uw);
    }

    @Override
    public void deleteBatch(List<String> returnIds) {
        returnIds.forEach(this::delete);
    }

    @Override
    public void offShelf(String returnId) {
        LambdaUpdateWrapper<IntegralReturnMerchant> uw = new LambdaUpdateWrapper<>();
        uw.set(IntegralReturnMerchant::getStatus, IntegralReturnMerchantStatusEnum.DISABLE.getStatus());
        uw.eq(IntegralReturnMerchant::getReturnId, returnId);
        update(uw);
    }

    @Override
    public IPage<IntegralReturnMerchantVO> page(String returnId, String name, Integer status, Integer pageNum, Integer pageSize) {
        overdue();
        IPage<IntegralReturnMerchantVO> page = new Page<>(pageNum, pageSize);
        IPage<IntegralReturnMerchantVO> iPage = baseMapper.page(page, returnId, name, status);
        return iPage;
    }

    @Override
    public IntegralReturnMerchantDetailVO detail(String returnId) {
        LambdaQueryWrapper<IntegralReturnMerchant> qw = new LambdaQueryWrapper<>();
        qw.eq(IntegralReturnMerchant::getReturnId, returnId);
        IntegralReturnMerchant returnMerchant = getOne(qw);
        IntegralReturnMerchantDetailVO detailVO = beanMapper.map(returnMerchant, IntegralReturnMerchantDetailVO.class);

        List<Category> categoryList = categoryService.listByReturn(returnId);
        detailVO.setCategoryList(categoryList);

        List<IntegralReturnSpu> returnSpus = integralReturnSpuService.list(new QueryWrapper<IntegralReturnSpu>().lambda().eq(IntegralReturnSpu::getReturnId, returnId));
        List<GoodsListVO> goodsListVO = new ArrayList<>();
        returnSpus.forEach(v -> {
            Spu spu = spuService.getByGoodsId(v.getGoodsId());
            GoodsListVO vo = beanMapper.map(spu, GoodsListVO.class);
            goodsListVO.add(vo);
        });
        detailVO.setGoodsList(goodsListVO);
        return detailVO;
    }

    public void overdue() {
        LambdaQueryWrapper<IntegralReturnMerchant> qw = new LambdaQueryWrapper<>();
        qw.ne(IntegralReturnMerchant::getStatus, IntegralReturnMerchantStatusEnum.DISABLE.getStatus());
        qw.ne(IntegralReturnMerchant::getStatus, IntegralReturnMerchantStatusEnum.DELETE.getStatus());
        qw.ne(IntegralReturnMerchant::getStatus, IntegralReturnMerchantStatusEnum.OVERDUE.getStatus());
        List<IntegralReturnMerchant> list = list(qw);
        list.forEach(v -> {
            if (v.getEffectiveStartTime() <= System.currentTimeMillis() && v.getEffectiveEndTime() >= System.currentTimeMillis()
                    && !v.getStatus().equals(IntegralReturnMerchantStatusEnum.DISABLE.getStatus())) {
                v.setStatus(IntegralReturnMerchantStatusEnum.ABLE.getStatus());
            }
            if (v.getEffectiveEndTime() < System.currentTimeMillis()) {
                v.setStatus(IntegralReturnMerchantStatusEnum.OVERDUE.getStatus());
            }
        });
        updateBatchById(list);
    }
}
