package com.mcwl.memberCenter.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mcwl.common.constant.QueueConstants;
import com.mcwl.common.core.domain.entity.SysUser;
import com.mcwl.memberCenter.domain.*;
import com.mcwl.memberCenter.enums.MemberBenefitTypeEnum;
import com.mcwl.memberCenter.enums.MemberEnum;
import com.mcwl.memberCenter.enums.PromotionEnum;
import com.mcwl.memberCenter.service.*;
import com.mcwl.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Component("userMemberTask")
@RequiredArgsConstructor
public class UserMemberTask {

    private final MemberService memberService;

    private final ISysUserService sysUserService;

    private final RabbitTemplate rabbitTemplate;

    private final MemberBenefitService memberBenefitService;

    private final BenefitService benefitService;

    private final PromotionService promotionService;

    private final MemberPromotionService memberPromotionService;


    /**
     * 积分重置提醒 月底前五天 0 0 9 L-5 * ?
     */
    public void emptyPointsRemindTask() {
        List<Member> memberList = memberService.getUseUserMember();
        if (memberList == null || memberList.isEmpty()) {
            return;
        }
        // 发送积分清零消息
        for (Member member : memberList) {
            rabbitTemplate.convertAndSend(QueueConstants.EMPTY_POINTS_REMIND_QUEUE, member);
        }

    }


    /**
     * 已弃用
     * 清空积分 每月月底前两天 0 0 0 L-2 * ?
     */
    @Transactional
    public void emptyPointsTsk() {
        List<Member> memberList = memberService.getUseUserMember();
        List<Long> userIdList = new ArrayList<>();
        List<SysUser> sysUserList = new ArrayList<>();
        if (memberList == null || memberList.isEmpty()) {
            return;
        }
        for (Member member : memberList) {
            member.setPoints(0.0);
            userIdList.add(member.getUserId());
        }
        sysUserList = sysUserService.listByIds(userIdList);
        for (SysUser sysUser : sysUserList) {
            sysUser.setFreePoints(0.0);
            sysUserService.updateUser(sysUser);
        }
        memberService.updateBatchById(memberList);
    }

    /**
     * 更新会员状态 间隔1h检查 0 0 0/1 * * ?
     */
    public void updateSubscriptionStatusTask() {
        LambdaQueryWrapper<Member> qw = new LambdaQueryWrapper<>();
        // endDate小于当前时间, subscriptionStatus不为过期
        qw.lt(Member::getEndDate, new Date())
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_EXPIRED)
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_PENDING);
        List<Member> memberList = memberService.list(qw);
        if (memberList == null || memberList.isEmpty()) {
            return;
        }

        for (Member member : memberList) {
            MemberEnum subscriptionStatus = member.getSubscriptionStatus();
            if (subscriptionStatus == MemberEnum.MEMBER_CENTER_ACTIVE) {
                // 如果subscriptionStatus是活跃的，表示连续包月。订阅状态改为"待支付"
                member.setSubscriptionStatus(MemberEnum.MEMBER_CENTER_PENDING);
                // nextBillingDate设置为当前会员结束日期的下个月的同一天,发送账单通知
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(member.getEndDate());
                calendar.add(Calendar.MONTH, 1);
                member.setNextBillingDate(calendar.getTime());
                memberService.updateById(member);
                // 发送会员账单消息，如果支付成功，更新last_payment_date，并重新计算end_date（start_date + 1个月）
                rabbitTemplate.convertAndSend(QueueConstants.MEMBER_BILLING_QUEUE, member);
            } else if (subscriptionStatus == MemberEnum.MEMBER_CENTER_INACTIVE) {
                // 不是连续包月，会员状态改为过期，状态改为"1"
                member.setSubscriptionStatus(MemberEnum.MEMBER_CENTER_EXPIRED);
                member.setStatus("1");
                member.setUpdateTime(new Date());
            }
        }
    }


    /**
     * 重置会员积分 每月1号 0 0 0 1 * ?
     */
    public void givePointsTask() {
        List<Member> memberList = memberService.getUseUserMember();
        for (Member member : memberList) {
            Long memberLevelId = member.getMemberLevelId();
            Double points = this.getPointsByMemberLevelId(memberLevelId);
            member.setPoints(points);
        }
        memberService.updateBatchById(memberList);
    }


    /**
     * 会员参与的促销活动是否过期 每天晚上0点检查 0 0 0 * * ?
     */
    @Transactional(rollbackFor = Exception.class)
    public void checkPromotionExpiredTask() {

        int pageNum = 1;
        int pageSize = 1000;

        // 根据活动结束日期小于当前时间，获取活动id
        List<Long> promotionIdList = new ArrayList<>();

        while (true) {
            Page<Promotion> page = new Page<>(pageNum, pageSize);

            promotionService.lambdaQuery()
                    .lt(Promotion::getEndTime, new Date()) // 活动结束日期小于当前时间
                    .orderByAsc(Promotion::getId)
                    .page(page);
            List<Promotion> promotionList = page.getRecords();
            if (promotionList.isEmpty()) {
                break;
            }
            for (Promotion promotion : promotionList) {
                promotionIdList.add(promotion.getId());
            }

            memberPromotionService.lambdaUpdate()
                    .set(MemberPromotion::getStatus, PromotionEnum.EXPIRED)
                    .eq(MemberPromotion::getStatus, PromotionEnum.PARTICIPATE)
                    .in(MemberPromotion::getPromotionId, promotionIdList)
                    .update();
            pageNum++;
            promotionIdList.clear();

        }
    }


    /**
     * 根据会员等级获取积分
     */
    public Double getPointsByMemberLevelId(Long memberLevelId) {

        // 根据会员等级id获取会员权益
        List<MemberBenefit> memberBenefitList = memberBenefitService.lambdaQuery()
                .eq(MemberBenefit::getMemberLevelId, memberLevelId)
                .list();

        // 根据会员权益id获取权益
        List<Long> benefitIdList = new ArrayList<>();
        for (MemberBenefit memberBenefit : memberBenefitList) {
            benefitIdList.add(memberBenefit.getBenefitId());
        }

        List<Benefit> benefitList = benefitService.lambdaQuery()
                .in(Benefit::getId, benefitIdList)
                .list();
        for (Benefit benefit : benefitList) {
            if (benefit.getBenefitType().getValue().equals(MemberBenefitTypeEnum.POINTS.getValue())) {
                return benefit.getBenefitDiscount();
            }
        }

        return 0.0;
    }


}
