package com.pcloud.book.applet.biz.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.setting.SettingUtil;
import com.pcloud.book.applet.biz.ReadBookRecordBiz;
import com.pcloud.book.applet.dao.ReadBookRecordDao;
import com.pcloud.book.applet.dto.ReadBookRecordDTO;
import com.pcloud.book.applet.entity.ReadBookRecord;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.NumberUtil;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.json.JSONUtils;
import com.pcloud.readercenter.common.enums.YesOrNoNumEnum;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.collections4.SetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static cn.hutool.core.date.DateUnit.SECOND;
import static com.pcloud.book.book.constant.BookConstant.BOOK_CACHE_MINUTE;

/**
 * (ReadBookRecord)表服务实现类
 *
 * @author makejava
 * @since 2021-02-04 15:33:44
 */
@Service("readBookRecordBiz")
public class ReadBookRecordBizImpl implements ReadBookRecordBiz {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReadBookRecordBizImpl.class);

    private static final String  redisKey4Reader = "BOOK:READER_ALL";

    @Autowired
    private ReadBookRecordDao readBookRecordDao;

    @Override
    @ParamLog("通过ID查询单条数据")
    public ReadBookRecord getById(Long id) {
        return readBookRecordDao.getById(id);
    }

    @Override
    @ParamLog("查询多条数据")
    public PageBeanNew getList(Integer currentPage, Integer numPerPage) {
        PageBeanNew pageBeanNew = readBookRecordDao.listPageNew(new PageParam(currentPage, numPerPage), null, "getList");
        List recordList = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(recordList)) {
            return pageBeanNew;
        }
        // 加载其它数据

        return pageBeanNew;
    }

    @Override
    @ParamLog("新增")
    public Long insert(ReadBookRecord readBookRecord) {
        readBookRecordDao.insert(readBookRecord);
        return readBookRecord.getId();
    }

    @Override
    @ParamLog("修改")
    public void update(ReadBookRecord readBookRecord) {
        if (readBookRecord == null || !NumberUtil.isNumber(readBookRecord.getId())) {
            throw BizException.PARAM_IS_NULL;
        }
        readBookRecordDao.update(readBookRecord);
    }

    @Override
    @ParamLog("删除")
    public void deleteById(Long id) {
        readBookRecordDao.deleteById(id);
    }

    @Override
    @ParamLog("新增用户阅读本书服务记录")
    public Long addReadBookRecord(ReadBookRecordDTO readBookRecordDTO) {
        Long bookId = readBookRecordDTO.getBookId();
        Long channelId = readBookRecordDTO.getChannelId();
        Long adviserId = readBookRecordDTO.getAdviserId();
        Long id = readBookRecordDTO.getId();
        String redisKey4Random = "BOOK:READER_COUNT:" + bookId + ":" + channelId + ":" + adviserId;
        String redisKey4Set = "BOOK:READER_SET:" + bookId + ":" + channelId + ":" + adviserId;
        Integer readerCount = null;
        //获取随机读者数
        if (JedisClusterUtils.exists(redisKey4Random)) {
            JedisClusterUtils.expire(redisKey4Random, BookConstant.BOOK_CACHE_SECOUND);
        } else {
            List<Integer> readerCountList = BookConstant.READER_COUNT_MAP.get(DateUtil.hour(new Date(), Boolean.TRUE));
            readerCount = RandomUtil.randomInt(readerCountList.get(0), readerCountList.get(1));
            JedisClusterUtils.set(redisKey4Random, readerCount.toString(), BookConstant.BOOK_CACHE_SECOUND);
        }
        //新增记录并获取当前在读人数
        if (Objects.equals(YesOrNoNumEnum.YES.getValue(), readBookRecordDTO.getRecordType())) {
            JedisClusterUtils.sadd(redisKey4Set, readBookRecordDTO.getWechatUserId().toString());
            JedisClusterUtils.expire(redisKey4Set, BookConstant.BOOK_CACHE_SECOUND);
            ReadBookRecord readBookRecord = new ReadBookRecord();
            //id为空 新记录 插入数据库 并新增到redis中
            BeanUtils.copyProperties(readBookRecordDTO, readBookRecord);
            SimpleDateFormat sbf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                readBookRecord.setStartTime(DateUtils.parseDate(sbf.format(new Date()),"yyyy-MM-dd HH:mm:ss"));
            } catch (ParseException e) {
               LOGGER.warn("addReadBookRecord时间转换失败");
            }
            readBookRecord.setLeaveType(YesOrNoNumEnum.NO.getValue());
            readBookRecordDao.insert(readBookRecord);
            id = readBookRecord.getId();
            JedisClusterUtils.hset(redisKey4Reader, id.toString(), JSONUtils.toJsonString(readBookRecord));
            JedisClusterUtils.expire(redisKey4Reader, BookConstant.BOOK_CACHE_SECOUND);
        } else if (Objects.equals(YesOrNoNumEnum.NO.getValue(), readBookRecordDTO.getRecordType())) {
            ReadBookRecord readBookRecord = readBookRecordDao.getById(id);
            readBookRecord.setRecordTime(null);
            readBookRecord.setEndTime(null);
            readBookRecord.setUpdateTime(null);
            JedisClusterUtils.srem(redisKey4Set, readBookRecordDTO.getWechatUserId().toString());
            JedisClusterUtils.expire(redisKey4Set, BookConstant.BOOK_CACHE_SECOUND);
            JedisClusterUtils.hdel(redisKey4Reader, id.toString());
            JedisClusterUtils.expire(redisKey4Reader, BookConstant.BOOK_CACHE_SECOUND);
            //id不为空 更新数据库时间 并从redis中删除
            Date endTime = new Date();
            readBookRecord.setEndTime(endTime);
            readBookRecord.setRecordTime(DateUtil.between(readBookRecord.getStartTime(), endTime, SECOND));
            readBookRecordDao.updateRecordTime(readBookRecord);
        }
        return id;
    }

    @Override
    public void autoDeleteReadBook() {
        Map<String, String> userMap = JedisClusterUtils.hgetAll(redisKey4Reader);
        if (MapUtils.isEmpty(userMap)) {
            LOGGER.info("autoDeleteReadBook, 缓存为空，返回");
            return;
        }
        Collection<String> smembers = userMap.values();
        List<ReadBookRecord> readBookRecords = new ArrayList<>();
        List<ReadBookRecord> readBookRecords4Expire = new ArrayList<>();
        smembers.stream().forEach(e ->{
            ReadBookRecord readBookRecord = JSONUtils.jsonToBean(e, ReadBookRecord.class);
            readBookRecords.add(readBookRecord);
        });
        if (ListUtils.isEmpty(readBookRecords)) {
            return;
        }
        readBookRecords.stream().forEach(e -> {
            Date startTime = e.getStartTime();
            long between = DateUtil.between(startTime, new Date(), SECOND);
            //查找开始时间与现在时间超过1分钟的数据
            if (between > BOOK_CACHE_MINUTE && null != e.getId()) {
                JedisClusterUtils.hdel(redisKey4Reader, e.getId().toString());
                e.setEndTime(DateUtil.offsetMinute(e.getStartTime(), 1));
                e.setRecordTime(Long.valueOf(BOOK_CACHE_MINUTE));
                e.setLeaveType(YesOrNoNumEnum.YES.getValue());
                readBookRecords4Expire.add(e);
            }
        });
        if (ListUtils.isEmpty(readBookRecords4Expire)) {
            return;
        }
        LOGGER.info("批量更新已过期的本书服务页浏览记录:{}", readBookRecords4Expire);
        readBookRecordDao.batchUpdateRecordTime(readBookRecords4Expire);
    }
}