package com.cpop.mall.framework.task;

import com.cpop.core.service.RedisService;
import com.cpop.core.utils.SpringUtils;
import com.cpop.mall.business.entity.ProductRecord;
import com.cpop.mall.business.service.ProductRecordService;
import com.cpop.mall.framework.constant.MallRedisConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_RECORD;

/**
 * @author DB
 * @createTime 2023/10/27 17:26
 * @description 凌晨同步库存任务
 */

@Component
@Slf4j
public class ProductRecordSyncStockTask {

    /**
     * @Description: 每天1点05分进行库存同步
     * @Author DB
     * @Date: 2023/10/28 10:08
     */
    @Scheduled(cron="0 5 1 * * ?")
    public void syncMysqlStockToRedis(){
        log.info("===============================开始<--库存信息同步-->开始===============================");
        //获取所有库存
        List<ProductRecord> productRecords = SpringUtils.getBean(ProductRecordService.class).list();
        RedisService redisService = SpringUtils.getBean(RedisService.class);
        productRecords.forEach(item->{
            redisService.setCacheObject(MallRedisConstant.STOCK_RECORD_NUM + item.getId(), item.getRecordNum());
            log.info("商品记录id为:{};商品库存为:{}", item.getId(), item.getRecordNum());
        });
        log.info("===============================结束<--库存信息结束-->结束===============================");
    }

    /**
     * @Description: 异步更新数据库
     * @param orderNumMap 产品记录库存
     * @Author DB
     * @Date: 2023/11/1 0:09
     */
    @Async("customAsyncThreadPool")
    public void asyncUpdateRecords(Map<String, Integer> orderNumMap) {
        loopUpdateStock(orderNumMap);
    }

    /**
     * @param orderNumMap 库存修改记录
     * @descriptions 循环插入库存修改记录
     * @author DB
     * @date 2023/11/01 17:01
     * @return: void
     */
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    protected void loopUpdateStock(Map<String, Integer> orderNumMap) {
        ProductRecordService productRecordService = SpringUtils.getBean(ProductRecordService.class);
        //用迭代器
        Iterator<Map.Entry<String, Integer>> iterator = orderNumMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> next = iterator.next();
            boolean update = productRecordService.updateChain()
                    .setRaw(PRODUCT_RECORD.RECORD_NUM, "record_num -" + next.getValue())
                    .where(PRODUCT_RECORD.ID.eq(next.getKey())).update();
            //如果更新成功，移除
            if (update) {
                iterator.remove();
            }
        }
        //存在更新失败(乐观锁),需要重新更新,直到全部成功
        if (!orderNumMap.isEmpty()) {
            //获取最新数据进行下一次循环
            loopUpdateStock(orderNumMap);
        }
    }
}
