package com.kym.service.admin.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.github.pagehelper.PageHelper;
import com.github.yulichang.base.MPJBaseServiceImpl;
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.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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
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.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.kym.entity.admin.Activity.APPLY_STATION_部分站点;
import static com.kym.entity.admin.Activity.DISCOUNT_TYPE_服务费折扣权益;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author skyline
 * @since 2023-10-18
 */
@Service
@DS("db-admin")
@Slf4j
public class ActivityServiceImpl extends MPJBaseServiceImpl<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;

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

    /**
     * 新增活动
     *
     * @param activityVo
     * @return
     */
    @Override
    @Transactional(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);
        }

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

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

    /**
     * 主活动列表
     *
     * @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())
                .gt(params.getStartTime() != null, Activity::getStartTime, params.getStartTime())
                .lt(params.getEndTime() != null, Activity::getEndTime, params.getEndTime())
                .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);
            }
        }
        return activityVo;
    }

    /**
     * 终止活动
     *
     * @param activityId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void terminateActivity(String activityId) {
        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();
    }

    /**
     * 异步处理充值活动
     *
     * @param userId
     * @param rechargeAmount
     */
    @Override
    @Async
    public void handleRechargeActivity(long userId, int rechargeAmount) {
        asyncHandleRechargeActivity(userId, rechargeAmount);
//        executor.execute(new RechargeActivityTask(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....");
    }

    /**
     * 处理充值活动
     */
    private class RechargeActivityTask implements Runnable {
        private final long userId;
        private final int rechargeAmount;

        public RechargeActivityTask(long userId, int rechargeAmount) {
            this.userId = userId;
            this.rechargeAmount = rechargeAmount;
        }

        @Override
        public void run() {
            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)
                        .ge(RechargeRights::getAmountMax, rechargeAmount) // 最后一档最大值设置成10000
                        .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....");
        }
    }
}
