package com.red.circle.other.app.scheduler.activity;

import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.component.redis.annotation.TaskCacheLock;
import com.red.circle.mq.business.model.event.BadgeOperateEvent;
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
import com.red.circle.other.domain.ranking.RankingActivityType;
import com.red.circle.other.domain.ranking.RankingCycleType;
import com.red.circle.other.infra.database.mongo.entity.activity.RankingActivityRecord;
import com.red.circle.other.infra.database.rds.entity.badge.BadgeBackpack;
import com.red.circle.other.infra.database.rds.service.badge.BadgeBackpackService;
import com.red.circle.other.infra.gateway.RankingActivityGateway;
import com.red.circle.other.inner.enums.material.BadgeBackpackExpireType;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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


@Slf4j
@Component
@RequiredArgsConstructor
public class RamadanRankingBadgeTask {

    private final BadgeBackpackService badgeBackpackService;
    private final UserMqMessageService userMqMessageService;
    private final RankingActivityGateway rankingActivityGateway;
    
    // 排名徽章ID数组：[第一名, 第二名, 第三名, 第四至十名]
    private final static Long[] BADGE_IDS = new Long[]{
            2021136719126454273L,  // 第一名
            2021136775078469633L,  // 第二名
            2021136820859297793L,  // 第三名
            2021136863104327681L,  // 第四至十名
    };

    /**
     * 每分钟发放和收回排名徽章
     */
    @Scheduled(cron = "0 0/1 * * * *", zone = "Asia/Riyadh")
    @TaskCacheLock(key = "RAMADAN_RANKING_BADGE_TASK", expireSecond = 20)
    public void sendWeekRankingReward() {
        try {
            // 获取前十名
            List<RankingActivityRecord> top10 = rankingActivityGateway.getRankingList(
                    SysOriginPlatformEnum.LIKEI.name(),
                    RankingActivityType.RAMADAN,
                    RankingCycleType.WEEKLY,
                    ZonedDateTimeAsiaRiyadhUtils.nowWeekMondayToInt().toString(),
                    null,
                    10
            );

            // 2. 查询所有持有排名徽章的用户
            List<BadgeBackpack> allBackpackList = badgeBackpackService.query()
                    .in(BadgeBackpack::getBadgeId, Arrays.asList(BADGE_IDS))
                    .list()
                    .stream()
                    .filter(RamadanRankingBadgeTask::filterAvailable)
                    .collect(Collectors.toList());

            // 3. 构建"用户应得徽章集合"：Map<userId, Set<badgeId>>
            Map<Long, Set<Long>> userShouldHaveBadgesMap = new HashMap<>();

            for (int rank = 0; rank < top10.size() && rank < 10; rank++) {
                RankingActivityRecord rankingData = top10.get(rank);
                Long badgeId = getBadgeIdByRank(rank);
                userShouldHaveBadgesMap.computeIfAbsent(rankingData.getUserId(), k -> new HashSet<>()).add(badgeId);
            }

            // 4. 构建"用户当前持有徽章集合"：Map<userId, Set<badgeId>>
            Map<Long, Set<Long>> userCurrentBadgesMap = new HashMap<>();
            for (BadgeBackpack backpack : allBackpackList) {
                userCurrentBadgesMap.computeIfAbsent(backpack.getUserId(), k -> new HashSet<>())
                        .add(backpack.getBadgeId());
            }

            // 5. 发放缺失的徽章
            for (Map.Entry<Long, Set<Long>> entry : userShouldHaveBadgesMap.entrySet()) {
                Long userId = entry.getKey();
                Set<Long> shouldHaveBadges = entry.getValue();
                Set<Long> currentBadges = userCurrentBadgesMap.getOrDefault(userId, Collections.emptySet());

                // 找出缺失的徽章（应得但当前没有的）
                for (Long badgeId : shouldHaveBadges) {
                    if (!currentBadges.contains(badgeId)) {
                        grantBadge(userId, badgeId);
                        log.info("排名徽章发放：userId={}, badgeId={}, badgeName={}", 
                                userId, badgeId, getBadgeNameById(badgeId));
                    }
                }
            }

            // 6. 收回多余的徽章
            for (Map.Entry<Long, Set<Long>> entry : userCurrentBadgesMap.entrySet()) {
                Long userId = entry.getKey();
                Set<Long> currentBadges = entry.getValue();
                Set<Long> shouldHaveBadges = userShouldHaveBadgesMap.getOrDefault(userId, Collections.emptySet());

                // 找出多余的徽章（当前有但不应得的）
                for (Long badgeId : currentBadges) {
                    if (!shouldHaveBadges.contains(badgeId)) {
                        revokeBadge(userId, badgeId);
                        log.info("排名徽章收回：userId={}, badgeId={}, badgeName={} (用户不在该排名中)",
                                userId, badgeId, getBadgeNameById(badgeId));
                    }
                }
            }

        } catch (Exception e) {
            log.error("排名徽章任务执行异常", e);
        }
    }

    /**
     * 根据排名获取徽章ID
     * @param rank 排名索引（0-9对应第1-10名）
     * @return 徽章ID
     */
    private Long getBadgeIdByRank(int rank) {
        if (rank == 0) {
            return BADGE_IDS[0]; // 第1名
        } else if (rank == 1) {
            return BADGE_IDS[1]; // 第2名
        } else if (rank == 2) {
            return BADGE_IDS[2]; // 第3名
        } else {
            return BADGE_IDS[3]; // 第4-10名
        }
    }

    /**
     * 根据徽章ID获取徽章名称（用于日志）
     */
    private String getBadgeNameById(Long badgeId) {
        if (badgeId.equals(BADGE_IDS[0])) {
            return "第1名徽章";
        } else if (badgeId.equals(BADGE_IDS[1])) {
            return "第2名徽章";
        } else if (badgeId.equals(BADGE_IDS[2])) {
            return "第3名徽章";
        } else if (badgeId.equals(BADGE_IDS[3])) {
            return "第4-10名徽章";
        }
        return "未知徽章";
    }

    /**
     * 检查用户是否已持有该徽章
     */
    private boolean hasUserBadge(List<BadgeBackpack> backpackList, Long userId, Long badgeId) {
        return backpackList.stream()
                .anyMatch(b -> Objects.equals(b.getUserId(), userId) 
                        && Objects.equals(b.getBadgeId(), badgeId));
    }

    private static boolean filterAvailable(BadgeBackpack badgeBackpack) {
        return Objects.equals(badgeBackpack.getExpireType(),
                BadgeBackpackExpireType.PERMANENT.name())
                || badgeBackpack.getExpireTime().after(TimestampUtils.now());
    }

    /**
     * 发放徽章
     */
    private void grantBadge(Long userId, Long badgeId) {
        BadgeOperateEvent event = new BadgeOperateEvent()
                .setUserId(userId)
                .setBadgeId(badgeId)
                .setDays(1L)
                .setOperationType(BadgeOperateEvent.OperationType.WEAR.name());

        userMqMessageService.sendBadgeOperateEvent(event);
    }

    /**
     * 收回徽章
     */
    private void revokeBadge(Long userId, Long badgeId) {
        BadgeOperateEvent event = new BadgeOperateEvent()
                .setUserId(userId)
                .setBadgeId(badgeId)
                .setDays(1L)
                .setOperationType(BadgeOperateEvent.OperationType.REMOVE.name());

        userMqMessageService.sendBadgeOperateEvent(event);
    }

}