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

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.activity.ActivityRechargeRankCO;
import com.red.circle.other.app.dto.clientobject.activity.UserRechargeRankCO;
import com.red.circle.other.app.dto.cmd.activity.ActivityRechargeRankCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.rds.dao.activity.UserActivityRechargeDAO;
import com.red.circle.other.infra.database.rds.dto.activity.ActivityRechargeRankDTO;
import com.red.circle.other.inner.model.dto.user.OwnSpecialIdDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.NumUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

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

/**
 * 活动充值排行榜查询执行器
 */
@Component
@RequiredArgsConstructor
public class ActivityRechargeRankExe {

    private final UserActivityRechargeDAO userActivityRechargeDAO;
    private final UserProfileGateway userProfileGateway;
    private final UserProfileAppConvertor userProfileAppConvertor;

    public ActivityRechargeRankCO execute(ActivityRechargeRankCmd cmd) {
        Page<ActivityRechargeRankDTO> page = new Page<>(cmd.getPageNo(), cmd.getPageSize());
        String rechargeType = null;
        IPage<ActivityRechargeRankDTO> rankPage = userActivityRechargeDAO.pageRechargeRank(page, cmd.getActivityId(), rechargeType);

        ActivityRechargeRankCO result = new ActivityRechargeRankCO();

        if (CollectionUtils.isEmpty(rankPage.getRecords())) {
            result.setTopList(Collections.emptyList());
            result.setCurrentUser(buildCurrentUserRank(cmd.getActivityId(), cmd.getReqUserId(), rechargeType));
            return result;
        }

        List<ActivityRechargeRankDTO> records = rankPage.getRecords();
        Set<Long> userIds = records.stream()
            .map(ActivityRechargeRankDTO::getUserId)
            .collect(Collectors.toSet());

        Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
            userProfileGateway.mapByUserIds(userIds)
        );

        List<UserRechargeRankCO> topList = new ArrayList<>();
        int rank = (int) ((cmd.getPageNo() - 1) * cmd.getPageSize() + 1);
        for (ActivityRechargeRankDTO dto : records) {
            UserProfileDTO userProfile = userProfileMap.get(dto.getUserId());
            if (Objects.isNull(userProfile)) {
                continue;
            }

            topList.add(new UserRechargeRankCO()
                .setRank(rank++)
                .setUserId(dto.getUserId())
                .setAccount(userProfile.getAccount())
                .setUserAvatar(userProfile.getUserAvatar())
                .setUserName(userProfile.getUserNickname())
                .setSpecialAccount(Optional.ofNullable(userProfile.getOwnSpecialId())
                    .map(OwnSpecialIdDTO::getAccount)
                    .orElse(null))
                    .setAmount("***"));
        }

        result.setTopList(topList);
        result.setCurrentUser(buildCurrentUserRank(cmd.getActivityId(), cmd.getReqUserId(), rechargeType));

        return result;
    }

    private UserRechargeRankCO buildCurrentUserRank(Long activityId, Long userId, String rechargeType) {
        BigDecimal totalAmount = userActivityRechargeDAO.getUserTotalAmount(userId, activityId, rechargeType);
        Integer rank = userActivityRechargeDAO.getUserRank(activityId, userId, rechargeType);

        UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
            userProfileGateway.getByUserId(userId)
        );

        if (Objects.isNull(userProfile)) {
            return null;
        }

        return new UserRechargeRankCO()
            .setRank(rank)
            .setUserId(userId)
            .setAccount(userProfile.getAccount())
            .setUserAvatar(userProfile.getUserAvatar())
            .setUserName(userProfile.getUserNickname())
            .setSpecialAccount(Optional.ofNullable(userProfile.getOwnSpecialId())
                .map(OwnSpecialIdDTO::getAccount)
                .orElse(null))
            .setAmount(Optional.ofNullable(totalAmount)
                .map(BigDecimal::toPlainString)
                .orElse("0"));
    }
}
