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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.other.app.dto.clientobject.activity.InviteIncomeStatisticsCO;
import com.red.circle.other.infra.database.rds.dao.user.user.InviteUserRechargeCommissionDAO;
import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRechargeCommission;
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
import com.red.circle.other.infra.enums.user.InviteTypeEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 获取邀请收益统计执行器
 * 
 * 表结构说明：
 * user_invite_user: userId(邀请人), inviteUserId(被邀请人)
 * user_invite_user_recharge_commission: userId(被邀请人-充值人), inviteUserId(邀请人-获得佣金人)
 *
 * @author system
 * @date 2025-01-22
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GetIncomeStatisticsExe {

    private final UserInviteUserDAO userInviteUserDAO;
    private final InviteUserRechargeCommissionDAO inviteUserRechargeCommissionDAO;

    /**
     * 执行获取邀请收益统计
     *
     * @param cmd 命令
     * @return 收益统计
     */
    public InviteIncomeStatisticsCO execute(AppExtCommand cmd) {
        Long userId = cmd.getReqUserId();

        // 查询当前用户邀请的所有用户（userId=邀请人）
        List<UserInviteUser> allInvites = userInviteUserDAO.selectList(
                new LambdaQueryWrapper<UserInviteUser>()
                        .eq(UserInviteUser::getUserId, userId) // userId是邀请人
        );

        // 筛选有效邀请
        List<Long> validInvitedUserIds = getValidInvitedUserIds(allInvites);

        // 计算总收益
        BigDecimal totalIncome = calculateTotalIncome(userId, validInvitedUserIds);

        // 计算今日收益
        BigDecimal todayIncome = calculateTodayIncome(userId, validInvitedUserIds);

        InviteIncomeStatisticsCO statistics = new InviteIncomeStatisticsCO();
        statistics.setTotalIncome(totalIncome);
        statistics.setTodayIncome(todayIncome);
        statistics.setValidInviteCount(validInvitedUserIds.size());
        statistics.setTodayInviteCount(getTodayInviteCount(allInvites));

        log.info("邀请收益统计, userId={}, totalIncome={}, todayIncome={}, validCount={}", 
                userId, totalIncome, todayIncome, validInvitedUserIds.size());

        return statistics;
    }

    private Integer getTodayInviteCount(List<UserInviteUser> allInvites) {
        return (int) allInvites.stream()
                .filter(e -> e.getCreateTime().toLocalDateTime().toLocalDate().equals(LocalDate.now()))
                .count();
    }

    /**
     * 获取有效邀请用户ID列表
     */
    private List<Long> getValidInvitedUserIds(List<UserInviteUser> allInvites) {
        return allInvites.stream()
//                .filter(this::isValidInvite)
                .map(UserInviteUser::getInviteUserId) // inviteUserId是被邀请人
                .collect(Collectors.toList());
    }

    /**
     * 判断是否为有效邀请
     */
    private boolean isValidInvite(UserInviteUser invite) {
        String inviteType = invite.getInviteType();
        
        // LOTTERY类型直接算有效
        if (InviteTypeEnum.LOTTERY.getCode().equals(inviteType)) {
            return true;
        }
        
        // REGISTER类型需要检查充值记录
        if (InviteTypeEnum.REGISTER.getCode().equals(inviteType)) {
            // userId=邀请人, inviteUserId=被邀请人
            return hasValidRecharge(invite.getInviteUserId(), invite.getUserId());
        }
        
        return false;
    }

    /**
     * 检查是否有有效充值记录（commission > 0）
     * @param invitedUserId 被邀请人 ID（充值的人）
     * @param inviterUserId 邀请人 ID（获得佣金的人）
     */
    private boolean hasValidRecharge(Long invitedUserId, Long inviterUserId) {
        Long count = inviteUserRechargeCommissionDAO.selectCount(
                new LambdaQueryWrapper<InviteUserRechargeCommission>()
                        .eq(InviteUserRechargeCommission::getUserId, invitedUserId) // 被邀请人
                        .eq(InviteUserRechargeCommission::getInviteUserId, inviterUserId) // 邀请人
                        .gt(InviteUserRechargeCommission::getCommission, BigDecimal.ZERO)
        );
        return count != null && count > 0;
    }

    /**
     * 计算总收益
     */
    private BigDecimal calculateTotalIncome(Long inviterUserId, List<Long> validInvitedUserIds) {
        if (validInvitedUserIds.isEmpty()) {
            return BigDecimal.ZERO;
        }

        List<InviteUserRechargeCommission> commissions = inviteUserRechargeCommissionDAO.selectList(
                new LambdaQueryWrapper<InviteUserRechargeCommission>()
                        .eq(InviteUserRechargeCommission::getUserId, inviterUserId)
                        .in(InviteUserRechargeCommission::getInviteUserId, validInvitedUserIds)
        );

        return commissions.stream()
                .map(InviteUserRechargeCommission::getCommission)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 计算今日收益
     */
    private BigDecimal calculateTodayIncome(Long inviterUserId, List<Long> validInvitedUserIds) {
        if (validInvitedUserIds.isEmpty()) {
            return BigDecimal.ZERO;
        }

        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        List<InviteUserRechargeCommission> todayCommissions = inviteUserRechargeCommissionDAO.selectList(
                new LambdaQueryWrapper<InviteUserRechargeCommission>()
                        .eq(InviteUserRechargeCommission::getUserId, inviterUserId)
                        .in(InviteUserRechargeCommission::getInviteUserId, validInvitedUserIds)
                        .ge(InviteUserRechargeCommission::getCreateTime, Timestamp.valueOf(todayStart))
                        .le(InviteUserRechargeCommission::getCreateTime, Timestamp.valueOf(todayEnd))
        );

        return todayCommissions.stream()
                .map(InviteUserRechargeCommission::getCommission)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}
