package com.ruoyi.xq.service.impl;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.xq.domain.User;
import com.ruoyi.xq.domain.UserStatus;
import com.ruoyi.xq.domain.UserVip;
import com.ruoyi.xq.domain.VipOrder;
import com.ruoyi.xq.dto.admin.user.UserVipAdminVo;
import com.ruoyi.xq.dto.admin.user.req.AddVipReq;
import com.ruoyi.xq.enums.common.OrderTypeEnum;
import com.ruoyi.xq.enums.pay.PayStatusEnum;
import com.ruoyi.xq.enums.pay.PlatformTypeEnum;
import com.ruoyi.xq.enums.vip.VipStatusEnum;
import com.ruoyi.xq.enums.vip.VipTypeEnum;
import com.ruoyi.xq.manager.OrderNoUtil;
import com.ruoyi.xq.mapper.UserVipMapper;
import com.ruoyi.xq.service.UserService;
import com.ruoyi.xq.service.UserStatusService;
import com.ruoyi.xq.service.UserVipService;
import com.ruoyi.xq.service.VipOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * VIP用户Service业务层处理
 *
 * @author 77
 * @date 2024-03-04
 */
@Service
public class UserVipServiceImpl extends ServiceImpl<UserVipMapper,UserVip> implements UserVipService {

    @Autowired
    private VipOrderService vipOrderService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserStatusService userStatusService;

    @Override
    public UserVip getUserVip(Long userId, Integer vipType){
        return this.getOne(Wrappers.lambdaQuery(UserVip.class)
                .eq(UserVip::getUserId, userId)
                .eq(UserVip::getVipType, vipType)
                .last("limit 1"));
    }

    @Override
    public UserVip getUserVipNormal(Long userId, Integer vipType){
        return this.getOne(Wrappers.lambdaQuery(UserVip.class)
                .eq(UserVip::getUserId, userId)
                .eq(UserVip::getVipType, vipType)
                .eq(UserVip::getVipStatus, VipStatusEnum.NORMAL.getCode())
                .ge(UserVip::getVipTimeout, LocalDateTime.now())
                .last("limit 1"));
    }

    @Override
    public UserVip getByUserVipMaster(Long userId){
        List<UserVip> userVipList = this.list(Wrappers.lambdaQuery(UserVip.class)
                .eq(UserVip::getUserId, userId)
                .eq(UserVip::getVipStatus, VipStatusEnum.NORMAL.getCode())
                .ge(UserVip::getVipTimeout, LocalDateTime.now()));
        return userVipList.stream().max(Comparator.comparing(UserVip::getVipType)).orElse(null);
    }

    @Override
    public List<UserVip> listUserVipMaster(List<Long> userIdArray){
        if(CollectionUtils.isEmpty(userIdArray)){
            return new ArrayList<>();
        }
        return baseMapper.listUserVipMaster(userIdArray);
    }

    /**
     * 后台管理强制覆盖VIP
     * @param bo
     * @param user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateVipOrderAdmin(AddVipReq bo, User user) {
        VipTypeEnum vipTypeEnum = VipTypeEnum.getByCode(bo.getOpenVipType());
        if(vipTypeEnum == null || bo.getOpenVipMonthNum() == null || bo.getOpenVipMonthNum() < 1){
            throw new ServiceException("参数异常!");
        }
        String text = String.format("管理员开通%s %s个月", vipTypeEnum.getText(), bo.getOpenVipMonthNum());
        VipOrder vipOrder = new VipOrder();
        vipOrder.setUserId(user.getId());
        vipOrder.setUsercode(user.getUsercode());
        vipOrder.setVipType(vipTypeEnum.getCode());
        vipOrder.setVipMonth(bo.getOpenVipMonthNum());
        vipOrder.setOrderName(text);
        vipOrder.setOrderNo(OrderNoUtil.gen(OrderTypeEnum.VIP));
        vipOrder.setPayStatus(PayStatusEnum.NO_PAY.getCode());
        vipOrder.setPlatformType(PlatformTypeEnum.ADMIN.getCode());
        vipOrder.setAdmin(true);
        vipOrder.setAdminId(LoginHelper.getUserId());
        vipOrderService.save(vipOrder);
        UserVipService userVipService = SpringUtil.getBean(UserVipService.class);
        userVipService.incsVip(user,bo.getOpenVipType(),bo.getOpenVipMonthNum());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void incsVip(User user, Integer vipType, Integer vipMonth){
        // TODO 加锁
        UserVip userVip = this.getUserVip(user.getId(),vipType);
        LocalDateTime now = LocalDateTime.now();
        // 以前会员失效
        if(userVip == null ||
                !VipStatusEnum.NORMAL.getCode().equals(userVip.getVipStatus()) || // 会员不可用
                userVip.getVipTimeout().isBefore(now)){
            if(userVip == null){
                userVip = new UserVip();
            }
            userVip.setUserId(user.getId());
            userVip.setUsercode(user.getUsercode());
            userVip.setVipType(vipType);
            LocalDate expireDate = now.plusMonths(vipMonth).plusDays(1).toLocalDate();
            userVip.setVipTimeout(LocalDateTime.of(expireDate, LocalTime.MIN));
            userVip.setVipStatus(VipStatusEnum.NORMAL.getCode());
            this.saveOrUpdate(userVip);
        }else{
            userVip.setVipTimeout(userVip.getVipTimeout().plusMonths(vipMonth));
            this.saveOrUpdate(userVip);
        }
        UserVipService service = SpringUtil.getBean(UserVipService.class);
        service.checkUserVip(userVip.getUserId());
    }

    @Override
    public Page<UserVipAdminVo> pageAdmin(PageQuery pageQuery, UserVipAdminVo bo) {
        return baseMapper.pageAdmin(pageQuery.build(), bo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeVip(Long id) {
        this.update(Wrappers.lambdaUpdate(UserVip.class)
                .eq(UserVip::getId,id)
                .set(UserVip::getVipStatus, VipStatusEnum.CLOSE.getCode()));
        UserVip userVip = this.getById(id);
        UserVipService service = SpringUtil.getBean(UserVipService.class);
        service.checkUserVip(userVip.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkUserVip(Long userId){
        UserVip vip = this.getByUserVipMaster(userId);
        if(vip == null){
            userStatusService.update(Wrappers.lambdaUpdate(UserStatus.class)
                    .eq(UserStatus::getUserId, userId)
                    .set(UserStatus::getPushVip, 0));
            userService.update(Wrappers.lambdaUpdate(User.class)
                    .eq(User::getId, userId)
                    .set(User::getOpenVip, false));
        }else{
            userService.update(Wrappers.lambdaUpdate(User.class)
                    .eq(User::getId, userId)
                    .set(User::getOpenVip, true)
                    .set(User::getVipType, vip.getVipType())
                    .set(User::getVipTimeout, vip.getVipTimeout()));
        }
    }


}
