package com.liquidnet.service.platform.service.impl.candy;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.common.cache.redis.util.AbstractRedisUtil;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.service.candy.constant.CandyRedisConst;
import com.liquidnet.service.candy.dto.CandyCommonCouponBasicDto;
import com.liquidnet.service.candy.entity.CandyCommonCoupon;
import com.liquidnet.service.candy.mapper.CandyCommonCouponMapper;
import com.liquidnet.service.platform.utils.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PlatformCandyCommonCouponService extends ServiceImpl<CandyCommonCouponMapper, CandyCommonCoupon> {

    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;

    /**
     * 移除公有券
     * - 处理已过期且过期天数超过`displayDays`的券
     *
     * @param currentDateTime 当前时间
     * @param displayDays     展示天数
     */
    public int rmvForCommonCouponProcessing(LocalDateTime currentDateTime, int displayDays) {
        AtomicInteger pl = new AtomicInteger();
        try {
            LambdaQueryWrapper<CandyCommonCoupon> commonCouponQueryWrapper = Wrappers.lambdaQuery(CandyCommonCoupon.class);
            commonCouponQueryWrapper.eq(CandyCommonCoupon::getState, 3);
            commonCouponQueryWrapper.le(CandyCommonCoupon::getUpdatedAt, currentDateTime.minusSeconds(displayDays));
            int totalCount = this.count(commonCouponQueryWrapper);
            int remainCount = totalCount, pSize = 1000;
            if (totalCount > 0) {
                log.info("券移除处理:公有券[总数:{},AT:{} - {} = {}] >>> BEGIN BEGIN BEGIN", totalCount, currentDateTime, displayDays, currentDateTime.minusDays(displayDays));
            }

            ArrayList<CandyCommonCoupon> updateCommonCouponList = ObjectUtil.getCandyCommonCouponArrayList();
            commonCouponQueryWrapper.select(CandyCommonCoupon::getMid, CandyCommonCoupon::getCcouponId);
            commonCouponQueryWrapper.orderByAsc(CandyCommonCoupon::getMid);
            while (remainCount > 0) {
                updateCommonCouponList.clear();

                LambdaQueryWrapper<CandyCommonCoupon> commonCouponLambdaQueryWrapper = commonCouponQueryWrapper.clone();
                String lastLimitSql = "LIMIT " + 0 + "," + pSize;
                commonCouponLambdaQueryWrapper.last(lastLimitSql);
                List<CandyCommonCoupon> commonCouponList = this.list(commonCouponLambdaQueryWrapper);

                for (int i = 0, listSize = CollectionUtils.isEmpty(commonCouponList) ? -1 : commonCouponList.size(); i < listSize; i++) {
                    CandyCommonCoupon commonCoupon = commonCouponList.get(i);
                    commonCoupon.setState(9);
                    commonCoupon.setOperator("RMV-DUED");
                    commonCoupon.setUpdatedAt(currentDateTime);

                    updateCommonCouponList.add(commonCoupon);
                }

                if (!CollectionUtils.isEmpty(updateCommonCouponList)) {
                    if (this.updateBatchById(updateCommonCouponList, updateCommonCouponList.size())) {
                        AbstractRedisUtil redisCandyUtil = redisDataSourceUtil.getRedisCandyUtil();
                        List<CandyCommonCouponBasicDto> vos = (List<CandyCommonCouponBasicDto>) redisCandyUtil.get(CandyRedisConst.BASIC_COMMON_COUPON);

                        if (!CollectionUtils.isEmpty(vos)) {
                            List<String> updateCommonCouponIdList = updateCommonCouponList.stream().map(CandyCommonCoupon::getCcouponId).collect(Collectors.toList());
                            int beforeSizeVos = vos.size();
                            vos.removeIf(r -> updateCommonCouponIdList.contains(r.getCcouponId()));

                            if (beforeSizeVos - vos.size() > 0) {
                                pl.getAndAdd(beforeSizeVos - vos.size());
                                if (vos.size() > 0) {
                                    redisCandyUtil.set(CandyRedisConst.BASIC_COMMON_COUPON, vos);
                                } else {
                                    redisCandyUtil.del(CandyRedisConst.BASIC_COMMON_COUPON);
                                }
                            }
                        }
                    } else {
                        throw new LiquidnetServiceException("-1", "券移除数据更新失败");
                    }
                }

                remainCount = Math.max(remainCount - pSize, 0);
                log.info("券移除处理中:公有券[总数:{},单次处理:{}|{},剩余:{}]", totalCount, lastLimitSql, pl.get(), remainCount);
            }
            if (totalCount > 0) {
                log.info("券移除处理:公有券[总数:{},处理总数:{}] >>> END END END", totalCount, pl.get());
            }
        } catch (Exception e) {
            log.error("Ex.券移除处理异常:公有券[currentDateTime={},displayDays={}]", currentDateTime, displayDays, e);
        }
        return pl.get();
    }
}
