package com.kym.service.admin.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.github.pagehelper.PageHelper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.kym.common.utils.CommUtil;
import com.kym.common.utils.IDGenerator;
import com.kym.entity.admin.*;
import com.kym.entity.admin.delay.DelayActivity;
import com.kym.entity.admin.queryParams.ActivityQueryParam;
import com.kym.entity.admin.vo.ActivityVo;
import com.kym.entity.common.PageBean;
import com.kym.entity.common.RedisKeys;
import com.kym.entity.miniapp.UserRechargeRights;
import com.kym.mapper.admin.ActivityMapper;
import com.kym.service.admin.*;
import com.kym.service.jobs.DelayService;
import com.kym.service.miniapp.UserRechargeRightsService;
import com.kym.service.mybatisplus.MyBaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

import static com.kym.entity.admin.Activity.*;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author skyline
 * @since 2023-10-18
 */
@Service
@DS("db-admin")
@Slf4j
public class ActivityServiceImpl extends MyBaseServiceImpl<ActivityMapper, Activity> implements ActivityService {

    private final ActivityStationService activityStationService;
    private final RechargeRightsService rechargeRightsService;
    private final UserRechargeRightsService userRechargeRightsService;
    private final StationService stationService;
    private final DelayService<DelayActivity> activityDelayService;
    private final BannerService bannerService;
    private final CouponService couponService;

    private final RedisTemplate<String, String> redisTemplate;


    public ActivityServiceImpl(ActivityStationService activityStationService, RechargeRightsService rechargeRightsService,
                               UserRechargeRightsService userRechargeRightsService, StationService stationService, @Lazy DelayService<DelayActivity> activityDelayService,
                               BannerService bannerService, CouponService couponService, RedisTemplate<String, String> redisTemplate) {
        this.activityStationService = activityStationService;
        this.rechargeRightsService = rechargeRightsService;
        this.userRechargeRightsService = userRechargeRightsService;
        this.stationService = stationService;
        this.activityDelayService = activityDelayService;
        this.bannerService = bannerService;
        this.couponService = couponService;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 新增活动
     *
     * @param activityVo
     * @return
     */
    @Override
    @DSTransactional(rollbackFor = Exception.class)
    public void createActivity(ActivityVo activityVo) {
        // 新增activity
        var activity = new Activity();
        BeanUtils.copyProperties(activityVo, activity);
        activity.setId(IDGenerator.INS().nextId());
        save(activity);

        // 新增activityStation 活动-站点关联
        if (activityVo.getApplyStation() == APPLY_STATION_部分站点 && !CommUtil.isEmptyOrNull(activityVo.getStationIds())) {
            var activityStationList = activityVo.getStationIds().stream().map(stationId -> new ActivityStation().setActivityId(activity.getId()).setStationId(stationId)).toList();
            activityStationService.saveBatch(activityStationList);
        }

        // 新增充值优惠活动
        if (activityVo.getDiscountType().equals(Activity.DISCOUNT_TYPE_服务费折扣权益) && !CommUtil.isEmptyOrNull(activityVo.getRechargeRightsList())) {
            var rechargeRightsList = activityVo.getRechargeRightsList().stream().peek(rechargeRights -> {
                BeanUtils.copyProperties(activity, rechargeRights, "id", "name");
                rechargeRights.setActivityId(activity.getId());
            }).toList();
            rechargeRightsService.saveBatch(rechargeRightsList);
        }

        // 新增优惠券活动
        if (activityVo.getDiscountType().equals(Activity.DISCOUNT_TYPE_优惠券) && !CommUtil.isEmptyOrNull(activityVo.getCouponList())) {
            List<Coupon> couponList = activityVo.getCouponList().stream().peek(coupon -> {
                BeanUtils.copyProperties(activity, coupon, "id", "name");
                coupon.setActivityId(activity.getId());
//                coupon.setStatus(Coupon.STATUS_有效);
            }).collect(Collectors.toList());
            couponService.saveBatch(couponList);
        }

        // 加入活动延迟启停队列
        activityDelayService.addToDelayQueue(new DelayActivity(activity.getId(), activity.getName(), activity.getStartTime(), DelayActivity.TYPE_启动, activity.getDiscountType()));
        activityDelayService.addToDelayQueue(new DelayActivity(activity.getId(), activity.getName(), activity.getEndTime(), DelayActivity.TYPE_结束, activity.getDiscountType()));
    }


    /**
     * 主活动列表
     *
     * @param params
     * @return
     */
    @Override
    public PageBean<Activity> listActivity(ActivityQueryParam params) {
        PageHelper.startPage(params.getPageNum(), params.getPageSize());
        var list = lambdaQuery()
                .like(!CommUtil.isEmptyOrNull(params.getName()), Activity::getName, params.getName())
                .eq(params.getStatus() != null, Activity::getStatus, params.getStatus())
                .eq(params.getDiscountType() != null, Activity::getDiscountType, params.getDiscountType())
                .gt(params.getStartTime() != null, Activity::getStartTime, params.getStartTime())
                .lt(params.getEndTime() != null, Activity::getEndTime, params.getEndTime())
                .orderByDesc(Activity::getId)
                .list();
        return new PageBean<>(list);
    }

    /**
     * 活动详情
     *
     * @param activityId
     * @return
     */
    @Override
    public ActivityVo activityDetail(String activityId) {
        var activity = lambdaQuery().eq(Activity::getId, activityId).one();
        var activityVo = new ActivityVo();
        BeanUtils.copyProperties(activity, activityVo);
        if (activity.getDiscountType().equals(DISCOUNT_TYPE_服务费折扣权益)) {
            var rechargeRightsList = rechargeRightsService.lambdaQuery().eq(RechargeRights::getActivityId, activityId).list();
            activityVo.setRechargeRightsList(rechargeRightsList);
            var activityStationIds = activityStationService.lambdaQuery().eq(ActivityStation::getActivityId, activityId).list().stream().map(ActivityStation::getStationId).toList();
            if (CommUtil.isNotEmptyAndNull(activityStationIds)) {
                activityVo.setStationIds(activityStationIds);
                var stationList = stationService.lambdaQuery().in(Station::getStationId, activityStationIds).list();
                activityVo.setStationList(stationList);
            }
        } else if (activity.getDiscountType().equals(DISCOUNT_TYPE_优惠券)) {
            List<Coupon> couponList = couponService.lambdaQuery().eq(Coupon::getActivityId, activityId).list();
            activityVo.setCouponList(couponList);
            var activityStationIds = activityStationService.lambdaQuery().eq(ActivityStation::getActivityId, activityId).list().stream().map(ActivityStation::getStationId).toList();
            if (CommUtil.isNotEmptyAndNull(activityStationIds)) {
                activityVo.setStationIds(activityStationIds);
                var stationList = stationService.lambdaQuery().in(Station::getStationId, activityStationIds).list();
                activityVo.setStationList(stationList);
            }
        }
        return activityVo;
    }

    /**
     * 终止活动
     *
     * @param activityId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void terminateActivity(String activityId) {
        var activity = lambdaQuery().eq(Activity::getId, activityId).one();
        if (activity != null) {
            // 根据活动类型分别处理
            if (activity.getDiscountType().equals(Activity.DISCOUNT_TYPE_服务费折扣权益)) {
                lambdaUpdate().set(Activity::getStatus, Activity.STATUS_已结束).eq(Activity::getId, activityId).update();
                rechargeRightsService.lambdaUpdate().set(RechargeRights::getStatus, Activity.STATUS_已结束).eq(RechargeRights::getActivityId, activityId).update();
                // 修改banner状态为失效
                bannerService.lambdaUpdate().set(Banner::getStatus, Banner.STATUS_有效).eq(Banner::getActivityId, activityId).update();
            }
            if (activity.getDiscountType().equals(Activity.DISCOUNT_TYPE_优惠券)) {
                var couponList = couponService.lambdaQuery().eq(Coupon::getActivityId, activityId).list();
                // 优惠券状态修改为已结束
                if (CommUtil.isNotEmptyAndNull(couponList)) {
                    couponService.updateBatchById(couponList.stream().peek(coupon -> coupon.setStatus(Activity.STATUS_已结束)).toList());

                    // redis 优惠券失效，删除数据
                    var userCoupons = redisTemplate.opsForSet().members(RedisKeys.COUPON_ID_TO_USERS);
                    if (userCoupons != null) {
                        couponList.forEach(coupon -> {
                            // 筛选出活动相关的数据
                            var coupon2user = userCoupons.stream().filter(userCoupon -> userCoupon.startsWith(String.valueOf(coupon.getId()))).toArray();
                            if (coupon2user.length > 0) {
                                redisTemplate.opsForSet().remove(RedisKeys.COUPON_ID_TO_USERS, coupon2user);
                            }
                        });
                    }

                }
            }
            // 修改活动状态
            lambdaUpdate().set(Activity::getStatus, Activity.STATUS_已结束).eq(Activity::getId, activityId).update();

            // 修改站点活动关联表状态
            activityStationService.lambdaUpdate().set(ActivityStation::getStatus, Activity.STATUS_已结束).eq(ActivityStation::getActivityId, activityId).update();
        }

    }

    /**
     * 异步处理充值活动
     *
     * @param userId
     * @param rechargeAmount
     */
    @Override
    @Async
    public void handleRechargeActivity(long userId, int rechargeAmount) {
        asyncHandleRechargeActivity(userId, rechargeAmount);
    }

    /**
     * 处理充值活动
     */
    @Transactional(rollbackFor = Exception.class)
    public void asyncHandleRechargeActivity(long userId, int rechargeAmount) {
        log.info("RechargeActivityTask run....");
        // 进行中的充值权益活动
        // 手动切换数据源
        DynamicDataSourceContextHolder.push("db-admin");
        var activity = lambdaQuery().eq(Activity::getDiscountType, DISCOUNT_TYPE_服务费折扣权益).eq(Activity::getStatus, Activity.STATUS_进行中).one();
        // 充值金额，匹配到到具体的充值权益，生成用户权益
        if (activity != null) {
            var rechargeRights = rechargeRightsService.lambdaQuery().eq(RechargeRights::getActivityId, activity.getId())
                    .le(RechargeRights::getAmountMin, rechargeAmount)
                    .gt(RechargeRights::getAmountMax, rechargeAmount)
                    .one();
            DynamicDataSourceContextHolder.poll();
            if (rechargeRights != null) {
                var userRechargeRights = new UserRechargeRights().setRightsId(rechargeRights.getId()).setUserId(userId).setRightsBalance(rechargeAmount);
                BeanUtils.copyProperties(rechargeRights, userRechargeRights, "id", "createTime", "updateTime");
                // 计算有效期
                var endTime = LocalDateTime.now().with(LocalTime.MAX).plusDays(rechargeRights.getValidity() - 1);
                // 手动切换数据源
                DynamicDataSourceContextHolder.push("db-miniapp");
                userRechargeRightsService.save(userRechargeRights.setStartTime(LocalDateTime.now()).setEndTime(endTime));
                DynamicDataSourceContextHolder.poll();
            }
        } else {
            DynamicDataSourceContextHolder.poll();
        }
        log.info("RechargeActivityTask run end....");
    }


    /**
     * 获取可参与的优惠券（主动领取）活动
     *
     * @return
     */
    @Override
    public List<Activity> getAvailableCouponActivities() {
        MPJLambdaWrapper<Activity> wrapper = JoinWrappers.lambda(Activity.class)
                .selectAll(Activity.class)
                .leftJoin(Coupon.class, Coupon::getActivityId, Activity::getId)
                .eq(Activity::getStatus, Coupon.STATUS_进行中)
                .eq(Coupon::getReceiveType, Coupon.RECEIVE_TYPE_主动领取);
        return this.selectJoinList(Activity.class, wrapper);
    }


}
