package com.mcwl.memberCenter.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mcwl.common.constant.HttpStatus;
import com.mcwl.common.core.domain.AjaxResult;
import com.mcwl.common.core.domain.entity.SysUser;
import com.mcwl.common.core.page.PageDomain;
import com.mcwl.common.core.page.TableDataInfo;
import com.mcwl.common.exception.ServiceException;
import com.mcwl.common.utils.DateUtils;
import com.mcwl.common.utils.SecurityUtils;
import com.mcwl.memberCenter.domain.*;
import com.mcwl.memberCenter.domain.vo.MemberVo;
import com.mcwl.memberCenter.domain.vo.RechargeRecordVO;
import com.mcwl.memberCenter.enums.MemberBenefitTypeEnum;
import com.mcwl.memberCenter.enums.MemberEnum;
import com.mcwl.memberCenter.enums.MemberPeriodicEnum;
import com.mcwl.memberCenter.enums.PromotionEnum;
import com.mcwl.memberCenter.mapper.MemberMapper;
import com.mcwl.memberCenter.mapper.PromotionMapper;
import com.mcwl.memberCenter.service.*;
import com.mcwl.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.util.*;

@Service
@RequiredArgsConstructor
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {

    private final MemberLevelService memberLevelService;

    private final ISysUserService sysUserService;

    private final MemberBenefitService memberBenefitService;

    private final PromotionMapper promotionMapper;

    private final MemberConsumeService memberConsumeService;

    private final BenefitService benefitService;

    private final RechargeRecordService rechargeRecordService;

    private static final Map<Long, MemberLevel> memberLevelMap = new HashMap<>();

    @PostConstruct
    public void initMemberLevelMap() {
        List<MemberLevel> memberLevelList = memberLevelService.list();
        if (memberLevelList != null && !memberLevelList.isEmpty()) {
            for (MemberLevel memberLevel : memberLevelList) {
                memberLevelMap.put(memberLevel.getId(), memberLevel);
            }
        }
    }

    @Override
    public Member createUserMember(Long userId, Long memberLevelId, String paymentMethod, Long promotionId) {
        if (userId == null) {
            return null;
        }
        SysUser user = sysUserService.selectUserById(userId);
        if (user == null || memberLevelId == null) {
            return null;
        }
        MemberLevel memberLevel = memberLevelService.getById(memberLevelId);
        if (memberLevel == null) {
            return null;
        }
        // 查询用户是否已经存在会员
        LambdaQueryWrapper<Member> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Member::getUserId, userId)
                // subscriptionStatus不为expired
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_EXPIRED)
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_PENDING)
                .orderBy(true, false, Member::getEndDate);
        List<Member> memberList = baseMapper.selectList(lqw);
        Member member = new Member();
        // 设置用户id
        member.setUserId(userId);
        // 设置会员id
        member.setMemberLevelId(memberLevelId);
        if (memberList != null && !memberList.isEmpty()) {
            Member lastMember = memberList.get(0);
            Date endDate = lastMember.getEndDate();
            // 设置会员开始时间和结束时间
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(endDate);
//            calendar.add(Calendar.DAY_OF_MONTH, 1);
            member.setStartDate(calendar.getTime());
            member.setEndDate(this.getEndDate(memberLevel.getSubscriptionPeriod(), calendar));
        } else {
            // 用户不存在会员
            // 设置会员开始时间和结束时间
            Calendar calendar = Calendar.getInstance();
            member.setStartDate(calendar.getTime());
            member.setEndDate(this.getEndDate(memberLevel.getSubscriptionPeriod(), calendar));
        }

        // 设置积分
        Benefit benefit = benefitService.getBenefitByType(memberLevelId, MemberBenefitTypeEnum.POINTS);
        if (Objects.nonNull(benefit)) {
            Double points = benefit.getBenefitDiscount();
            // 根据活动id查询活动类型，如果为积分，则积分加成
            if (promotionId != null) {
                Promotion promotion = promotionMapper.selectById(promotionId);
                if (Objects.nonNull(promotion)) {
                    if (promotion.getActivityType() == PromotionEnum.POINTS) {
                        points = points + promotion.getActivityValue();
                    }
                }
            }
            member.setPoints(points);
        }

        // 设置订阅状态
        if (memberLevel.getSubscriptionPeriod() == MemberPeriodicEnum.CONTINUE_MONTH) {
            // 连续包月，会员状态为活跃
            member.setSubscriptionStatus(MemberEnum.MEMBER_CENTER_ACTIVE);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(member.getEndDate());
            calendar.add(Calendar.MONTH, 1);
            member.setNextBillingDate(calendar.getTime());
        } else {
            member.setSubscriptionStatus(MemberEnum.MEMBER_CENTER_INACTIVE);
        }
        // 设置支付时间
        member.setLastPaymentDate(new Date());
        // 设置支付方式
        member.setPaymentMethod(paymentMethod);

        baseMapper.insert(member);


        return member;
    }


    @Override
    public List<Member> getUseUserMember() {
        return this.getUseUserMember(null);
    }

    @Override
    public Member getUseUserMemberByUserId(Long userId) {

        List<Member> memberList = this.getUseUserMember(userId);
        if (memberList == null || memberList.isEmpty()) {
            return null;
        }
        return memberList.get(0);
    }

    @Override
    public Member rechargePoints(Long userId, Double points) {
        if (userId == null) {
            return null;
        }
        if (points == null) {
            return null;
        }
        Member member = getUseUserMemberByUserId(userId);
        if (member != null) {
            member.setPoints(member.getPoints() + points);
            baseMapper.updateById(member);
            return member;
        }
        return null;
    }

    @Override
    public Member latestSubscription(Long userId) {
        // 根据userId 查询会员，按创建时间降序，获取最新的会员
        LambdaQueryWrapper<Member> qw = new LambdaQueryWrapper<>();
        qw.eq(Member::getUserId, userId)
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_EXPIRED)
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_PENDING)
                .orderByDesc(Member::getCreateTime);
        List<Member> memberList = baseMapper.selectList(qw);
        if (memberList != null && !memberList.isEmpty()) {
            return memberList.get(0);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void consumePoints(Double consumePoints) {
        Long userId = SecurityUtils.getUserId();
        SysUser sysUser = sysUserService.selectUserById(userId);
        Member member = this.getUseUserMemberByUserId(userId);
        // 用户的免费积分
        Double freePoints = sysUser.getFreePoints();
        // 会员积分
        Double memberPoints = 0.0;
        if (member != null) {
            memberPoints = member.getPoints();
        }
        // 获取用户的总积分
        double points = freePoints + memberPoints;
        if (points < consumePoints) {
            throw new ServiceException("积分不足");
        }

        // 保存消费记录
        saveMemberConsume(consumePoints, userId, points);

        // 先扣除会员的积分
        if (member != null) {
            double mp = member.getPoints() - consumePoints;
            if (mp >= 0) {
                member.setPoints(mp);
                consumePoints = 0.0;
            } else {
                member.setPoints(0D);
                consumePoints = consumePoints - memberPoints;
            }
            baseMapper.updateById(member);
        }
        // consumePoints有剩余再扣除用户的积分
        if (consumePoints > 0) {
            sysUser.setFreePoints(freePoints - consumePoints);
            sysUserService.updateUser(sysUser);
        }

    }

    @Override
    public Double calculatePayment(Double unitPrice, Long promotionId) {
        if (Objects.isNull(promotionId)) {
            return unitPrice;
        }

        Promotion promotion = promotionMapper.selectById(promotionId);
        if (Objects.isNull(promotion)) {
            return unitPrice;
        }
        PromotionEnum activityType = promotion.getActivityType();
        if (activityType == PromotionEnum.DISCOUNT) {
            return unitPrice * promotion.getActivityValue();
        }

        return unitPrice;
    }

    private void saveMemberConsume(Double consumePoints, Long userId, double points) {
        MemberConsume memberConsume = new MemberConsume();
        memberConsume.setUserId(userId);
        memberConsume.setConsumePoints(consumePoints);
        memberConsume.setRemainingPoints(points - consumePoints);
        memberConsume.setConsumeTime(new Date());
        memberConsumeService.save(memberConsume);
    }

    /**
     * @return 按用户id获取正常的会员集合
     */
    @Override
    public List<MemberVo> getValidMemberById(Long userId) {

        List<Member> memberList = this.getValidMember(userId);
        List<MemberVo> memberVoList = new ArrayList<>();
        for (Member member : memberList) {
            MemberVo memberVo = BeanUtil.copyProperties(member, MemberVo.class);
            MemberLevel memberLevel = memberLevelMap.get(member.getMemberLevelId());
            if (Objects.nonNull(memberLevel)) {
                memberVo.setMemberLevelName(memberLevel.getMemberName());
            }
            memberVoList.add(memberVo);
        }

        return memberVoList;
    }

    private List<Member> getUseUserMember(Long userId) {
        // startDate 小于等于当前时间、endDate 大于等于当前时间
        // subscriptionStatus 不为 "过期" 或 "待支付"
        // status 为 0 的
        LambdaQueryWrapper<Member> qw = new LambdaQueryWrapper<>();
        qw.le(Member::getStartDate, new Date())
                .ge(Member::getEndDate, new Date())
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_EXPIRED)
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_PENDING)
                .eq(Member::getStatus, "0")
                .eq(userId != null, Member::getUserId, userId);
        return baseMapper.selectList(qw);
    }

    /**
     * 获取有效的会员集合
     * @param userId 用户id
     * @return 有效的会员集合
     */
    private List<Member> getValidMember(Long userId) {
        // startDate 小于等于当前时间、endDate 大于等于当前时间
        // subscriptionStatus 不为 "过期" 或 "待支付"
        // status 为 0 的
        LambdaQueryWrapper<Member> qw = new LambdaQueryWrapper<>();
        qw.ge(Member::getEndDate, new Date())
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_EXPIRED)
                .ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_PENDING)
                .eq(Member::getStatus, "0")
                .eq(userId != null, Member::getUserId, userId);
        return baseMapper.selectList(qw);
    }


    /**
     * 根据订阅周期和开始时间 计算结束时间
     *
     * @param subscriptionPeriod 订阅周期
     * @param calendar           结束时间（日历）
     * @return 结束时间
     */
    private Date getEndDate(MemberPeriodicEnum subscriptionPeriod, Calendar calendar) {
        switch (subscriptionPeriod) {
            case YEAR:
                calendar.add(Calendar.YEAR, 1);
                break;
            case QUARTER:
                calendar.add(Calendar.MONTH, 3);
                break;
            case MONTH:
            case CONTINUE_MONTH:
                calendar.add(Calendar.MONTH, 1);
                break;
            default:
                break;
        }
        return calendar.getTime();
    }


    @Override
    public TableDataInfo getRechargePoints(PageDomain pageDomain) {

        Page<RechargeRecord> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());

        rechargeRecordService.page(page, new LambdaQueryWrapper<RechargeRecord>()
                .eq(RechargeRecord::getUserId, SecurityUtils.getUserId()));

        List<RechargeRecord> rechargeRecordList = page.getRecords();

        List<RechargeRecordVO> rechargeRecordVOList = new ArrayList<>();

        for (RechargeRecord rechargeRecord : rechargeRecordList) {
            RechargeRecordVO rechargeRecordVO = new RechargeRecordVO();
            BeanUtil.copyProperties(rechargeRecord, rechargeRecordVO);
            rechargeRecordVO.setRechargeTime(rechargeRecord.getCreateTime());
            rechargeRecordVOList.add(rechargeRecordVO);
        }

        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(rechargeRecordVOList);
        rspData.setTotal(page.getTotal());

        return rspData;
    }
}
