package com.sonic.frog.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sonic.frog.dao.UserCreateCountStatDao;
import com.sonic.frog.domain.entity.UserCreateCountStat;
import com.sonic.frog.domain.output.UserCreateCountOutput;
import com.sonic.frog.enums.ToastResultCode;
import com.sonic.frog.service.UserCreateCountStatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户相册创作次数统计 Service实现类
 */
@Slf4j
@Service
public class UserCreateCountStatServiceImpl extends ServiceImpl<UserCreateCountStatDao, UserCreateCountStat> implements UserCreateCountStatService {

    @Autowired
    private UserCreateCountStatDao userCreateCountStatDao;

    /**
     * 免费创建图片数量
     */
    private final static Integer FREE_NUM = 10;

    /**
     * 会员赠送创建图片数量
     */
    private final static Integer MEMBER_NUM = 10;

    /**
     * 会员赠送次数周期天数，每隔30天赠送一次
     */
    private final static Integer MEMBER_GIFT_DAY = 30;

    @Override
    public void addBuyNum(Long userId, Integer count) {
        userCreateCountStatDao.addBuyNum(userId, count);
    }

    @Override
    public void subMemberGiftUserCreateCount(Long userId, LocalDateTime startTime, LocalDateTime expireTime) {
        UserCreateCountStat userCreateCountStat = initUserCreateCountStat(userId);
        if (userCreateCountStat.getMemberExpTime() == null) {
            //首次成为会员
            userCreateCountStat.setMemberNum(MEMBER_NUM);
            //加30天，记录下次赠送时间
            userCreateCountStat.setNextGiftTime(startTime.plusDays(MEMBER_GIFT_DAY));
            //记录会员过期时间
            userCreateCountStat.setMemberExpTime(expireTime);
        } else {
            if (startTime.isAfter(userCreateCountStat.getMemberExpTime())) {
                //过期后订阅
                userCreateCountStat.setMemberNum(userCreateCountStat.getMemberNum() + MEMBER_NUM);
                userCreateCountStat.setNextGiftTime(startTime.plusDays(MEMBER_GIFT_DAY));
                userCreateCountStat.setMemberExpTime(expireTime);
            } else {
                //有效期内续订,只更新会员过期时间就行了
                userCreateCountStat.setMemberExpTime(expireTime);
            }
        }
        //更新数据库
        updateById(userCreateCountStat);
    }

    private UserCreateCountStat initUserCreateCountStat(Long userId) {
        UserCreateCountStat userCreateCountStat = getOne(Wrappers.<UserCreateCountStat>lambdaQuery().eq(UserCreateCountStat::getUserId, userId).last("limit 1"));
        if (userCreateCountStat == null) {
            userCreateCountStat = new UserCreateCountStat();
            userCreateCountStat.setUserId(userId);
            userCreateCountStat.setFreeNum(FREE_NUM);
            userCreateCountStat.setUsedFreeNum(0);
            userCreateCountStat.setMemberNum(0);
            userCreateCountStat.setUsedMemberNum(0);
            userCreateCountStat.setBuyNum(0);
            userCreateCountStat.setUsedBuyNum(0);
            userCreateCountStat.setCreateTime(LocalDateTime.now());
            userCreateCountStat.setEditTime(LocalDateTime.now());
            save(userCreateCountStat);
        }
        return userCreateCountStat;
    }

    @Override
    public UserCreateCountOutput getUserCreateCount(Long userId) {
        //查询用户创作次数，没有的话，初始化
        UserCreateCountStat userCreateCountStat = initUserCreateCountStat(userId);
        return UserCreateCountOutput.builder().freeNum(userCreateCountStat.getFreeNum()).usedFreeNum(userCreateCountStat.getUsedFreeNum()).memberNum(userCreateCountStat.getMemberNum()).usedMemberNum(userCreateCountStat.getUsedMemberNum()).buyNum(userCreateCountStat.getBuyNum()).usedBuyNum(userCreateCountStat.getUsedBuyNum()).build();
    }

    @Override
    public void useUserCreateCount(Long userId) {
        UserCreateCountStat userCreateCountStat = getOne(Wrappers.<UserCreateCountStat>lambdaQuery().eq(UserCreateCountStat::getUserId, userId).last("limit 1"));
        ToastResultCode.USER_CREATE_COUNT_NONE.check(userCreateCountStat == null);
        if (userCreateCountStat.getFreeNum() > 0 && userCreateCountStat.getUsedFreeNum() < userCreateCountStat.getFreeNum()) {
            //免费次数还有，已使用+1
            userCreateCountStat.setUsedFreeNum(userCreateCountStat.getUsedFreeNum() + 1);
        } else if (userCreateCountStat.getMemberNum() > 0 && userCreateCountStat.getUsedMemberNum() < userCreateCountStat.getMemberNum()) {
            //会员赠送次数还有，已使用+1
            userCreateCountStat.setUsedMemberNum(userCreateCountStat.getUsedMemberNum() + 1);
        } else if (userCreateCountStat.getBuyNum() > 0 && userCreateCountStat.getUsedBuyNum() < userCreateCountStat.getBuyNum()) {
            //购买次数还有，已使用+1
            userCreateCountStat.setUsedBuyNum(userCreateCountStat.getUsedBuyNum() + 1);
        } else {
            ToastResultCode.USER_CREATE_COUNT_NONE.check(true);
        }
        //更新数据库
        update(userCreateCountStat, Wrappers.<UserCreateCountStat>lambdaUpdate().eq(UserCreateCountStat::getId, userCreateCountStat.getId()));
    }

    @Override
    public void giftMemberNumJob() {
        //获取待赠送会员次数的列表
        List<UserCreateCountStat> userCreateCountStatList = userCreateCountStatDao.getWaitingGiftMemberNumList();
        userCreateCountStatList.forEach(userCreateCountStat -> {
            if (userCreateCountStat.getNextGiftTime().isBefore(LocalDateTime.now())) {
                //如果下次赠送时间在会员过期时间之后，则下次赠送时间置空
                LocalDateTime nextGiftTime = userCreateCountStat.getNextGiftTime().plusDays(MEMBER_GIFT_DAY);
                //加5分钟，防止最后一次又赠送
                if (nextGiftTime.plusMinutes(5).isAfter(userCreateCountStat.getMemberExpTime())) {
                    nextGiftTime = null;
                }
                //更新数据库
                update(Wrappers.<UserCreateCountStat>lambdaUpdate()
                        .set(UserCreateCountStat::getMemberNum, userCreateCountStat.getMemberNum() + MEMBER_NUM)
                        .set(UserCreateCountStat::getNextGiftTime, nextGiftTime)
                        .eq(UserCreateCountStat::getId, userCreateCountStat.getId()));
            }
        });
    }
}