package com.red.circle.other.app.command.bd.query;

import com.alibaba.fastjson.JSON;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.order.inner.model.dto.MonthlyRechargeSummaryVO;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.BdTeamMemberCO;
import com.red.circle.other.app.dto.clientobject.BdTeamSummaryCO;
import com.red.circle.other.app.dto.h5.RechargeSummaryVO;
import com.red.circle.other.app.service.recharge.RechargeUserService;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.mongo.dto.team.TeamBillMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamBillCycle;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamBillCycleService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentBaseInfo;
import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentTeam;
import com.red.circle.other.infra.database.rds.entity.team.RoomBdLead;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentBaseInfoService;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentTeamService;
import com.red.circle.other.infra.database.rds.service.team.RoomBdLeadService;
import com.red.circle.other.inner.enums.team.TeamBillCycleStatus;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * BD团队总览查询执行器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class BdTeamSummaryQryExe {

    private final BusinessDevelopmentTeamService businessDevelopmentTeamService;
    private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService;
    private final TeamBillCycleService teamBillCycleService;
    private final TeamProfileService teamProfileService;
    private final TeamMemberTargetService teamMemberTargetService;
    private final TeamPolicyManagerService teamPolicyManagerService;
    private final UserProfileGateway userProfileGateway;
    private final UserProfileAppConvertor userProfileAppConvertor;
    private final RoomBdLeadService roomBdLeadService;
    private final RedisService redisService;
    private final RechargeUserService rechargeUserService;

    /**
     * 执行查询
     */
    public BdTeamSummaryCO execute(Long userId) {
        // 缓存查询
        String cacheKey = "bdteam:summary:" + userId;
        BdTeamSummaryCO cached = redisService.getStringToObject(cacheKey, BdTeamSummaryCO.class);
        if (cached != null) {
            return cached;
        }

        // 查询数据
        BdTeamSummaryCO result = queryTeamSummary(userId);

        // 缓存结果（2分钟）
        redisService.setString(cacheKey, JSON.toJSONString(result), 2, TimeUnit.MINUTES);

        return result;
    }

    /**
     * 查询团队总览
     */
    private BdTeamSummaryCO queryTeamSummary(Long userId) {
        BdTeamSummaryCO summary = new BdTeamSummaryCO();

        // 获取当前账单周期
        Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong();

        // 查询三个角色的数据
        BdTeamSummaryCO.TeamSummaryItem bdLeaderTeams = queryBdLeaderSummary(userId, currentBillBelong);
        BdTeamSummaryCO.TeamSummaryItem bdTeams = queryBdSummary(userId, currentBillBelong);
        BdTeamSummaryCO.TeamSummaryItem agencyTeams = queryAgencySummary(userId, currentBillBelong);
        BdTeamSummaryCO.TeamSummaryItem rechargeTeams = queryRechargeTeamsSummary(userId);

        summary.setBdLeaderTeams(bdLeaderTeams);
        summary.setBdTeams(bdTeams);
        summary.setAgencyTeams(agencyTeams);
        summary.setRechargeTeams(rechargeTeams);

        // Team earnings this period = BD Teams 的 totalIncome
        summary.setTeamEarningsThisPeriod(bdTeams.getTotalIncome());

        return summary;
    }

    /**
     * 查询 BD Leader 汇总
     */
    private BdTeamSummaryCO.TeamSummaryItem queryBdLeaderSummary(Long bdLeaderUserId, Integer currentBillBelong) {
        BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();

        // 查询该 Leader 下的所有 BD
        List<BusinessDevelopmentBaseInfo> bdList =
                businessDevelopmentBaseInfoService.listBdByLeadUserId(bdLeaderUserId);

        if (CollectionUtils.isEmpty(bdList)) {
            item.setCount(0);
            item.setTotalIncome(BigDecimal.ZERO);
            return item;
        }

        // 过滤BD Leader
        Set<Long> bdIdSet = bdList.stream()
                .map(BusinessDevelopmentBaseInfo::getUserId)
                .collect(Collectors.toSet());
        List<RoomBdLead> roomBdLeads = roomBdLeadService.listByUserIds(bdIdSet);
        
        if (CollectionUtils.isEmpty(roomBdLeads)) {
            item.setCount(0);
            item.setTotalIncome(BigDecimal.ZERO);
            return item;
        }

        List<Long> bdLeaderIdList = roomBdLeads.stream()
                .map(RoomBdLead::getUserId)
                .toList();
        bdList = bdList.stream()
                .filter(e -> !e.getUserId().equals(bdLeaderUserId))
                .filter(e -> bdLeaderIdList.contains(e.getUserId()))
                .collect(Collectors.toList());

        item.setCount(bdList.size());

        // 汇总所有 BD 的收入
        BigDecimal totalIncome = BigDecimal.ZERO;
        for (BusinessDevelopmentBaseInfo bdInfo : bdList) {
            List<BusinessDevelopmentTeam> bdTeamList =
                    businessDevelopmentTeamService.listByUserId(bdInfo.getUserId());
            if (CollectionUtils.isNotEmpty(bdTeamList)) {
                BigDecimal bdIncome = calculateBdTotalIncome(bdTeamList, currentBillBelong);
                totalIncome = totalIncome.add(bdIncome);
            }
        }

        item.setTotalIncome(totalIncome);
        return item;
    }

    /**
     * 查询 BD 汇总
     */
    private BdTeamSummaryCO.TeamSummaryItem queryBdSummary(Long bdUserId, Integer currentBillBelong) {
        BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();

        // 查询该用户下的所有 Agency 团队
        List<BusinessDevelopmentTeam> bdTeamList = businessDevelopmentTeamService.listByUserId(bdUserId);

        if (CollectionUtils.isEmpty(bdTeamList)) {
            item.setCount(0);
            item.setTotalIncome(BigDecimal.ZERO);
            return item;
        }

        List<BusinessDevelopmentBaseInfo> bdInfos = businessDevelopmentBaseInfoService.listBdByLeadUserId(bdUserId);
        item.setCount(bdInfos.size());

        // 计算总收入
        BigDecimal totalIncome = calculateBdTotalIncome(bdTeamList, currentBillBelong);
        item.setTotalIncome(totalIncome);

        return item;
    }

    /**
     * 查询 Agency 汇总
     */
    private BdTeamSummaryCO.TeamSummaryItem queryAgencySummary(Long agencyUserId, Integer currentBillBelong) {
        BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();

        // 查询该用户的所有团队
        List<BusinessDevelopmentTeam> bdTeamList = businessDevelopmentTeamService.listByUserId(agencyUserId);

        if (CollectionUtils.isEmpty(bdTeamList)) {
            item.setCount(0);
            item.setTotalIncome(BigDecimal.ZERO);
            return item;
        }

        item.setCount(bdTeamList.size());

        // 获取团队ID集合
        Set<Long> teamIdSet = bdTeamList.stream()
                .map(BusinessDevelopmentTeam::getTeamId)
                .collect(Collectors.toSet());

        // 查询账单数据
        Map<Long, TeamBillCycle> billCycleMap = teamBillCycleService.mapByTeamIds2(
                teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID);

        Map<Long, List<TeamMemberTarget>> memberTargetMap =
                teamMemberTargetService.mapMemberBillTarget(teamIdSet, currentBillBelong);

        // 查询区域政策
        Map<String, TeamPolicyManager> policyManagerMap = teamPolicyManagerService.mapRegionRelease(
                billCycleMap.values().stream()
                        .map(TeamBillCycle::getRegion)
                        .collect(Collectors.toSet()));

        // 计算总收入
        BigDecimal totalIncome = BigDecimal.ZERO;
        for (BusinessDevelopmentTeam bdTeam : bdTeamList) {
            BigDecimal teamIncome = getTeamTotalSalary(
                    billCycleMap, memberTargetMap, policyManagerMap, bdTeam.getTeamId());
            totalIncome = totalIncome.add(teamIncome);
        }

        item.setTotalIncome(totalIncome);
        return item;
    }

    /**
     * 计算 BD 的总收入（汇总其所有 Agency 团队的收入）
     */
    private BigDecimal calculateBdTotalIncome(List<BusinessDevelopmentTeam> bdTeamList, Integer currentBillBelong) {
        // 1. 获取所有团队ID
        Set<Long> teamIdSet = bdTeamList.stream()
                .map(BusinessDevelopmentTeam::getTeamId)
                .collect(Collectors.toSet());

        // 2. 查询账单周期
        Map<Long, TeamBillCycle> billCycleMap = teamBillCycleService.mapByTeamIds2(
                teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID);

        // 3. 查询成员目标
        Map<Long, List<TeamMemberTarget>> memberTargetMap =
                teamMemberTargetService.mapMemberBillTarget(teamIdSet, currentBillBelong);

        // 4. 查询区域政策
        Map<String, TeamPolicyManager> policyManagerMap = teamPolicyManagerService.mapRegionRelease(
                billCycleMap.values().stream()
                        .map(TeamBillCycle::getRegion)
                        .collect(Collectors.toSet()));

        // 5. 计算每个团队的收入并汇总
        BigDecimal totalIncome = BigDecimal.ZERO;
        for (BusinessDevelopmentTeam bdTeam : bdTeamList) {
            Long teamId = bdTeam.getTeamId();
            BigDecimal teamIncome = getTeamTotalSalary(billCycleMap, memberTargetMap, policyManagerMap, teamId);
            totalIncome = totalIncome.add(teamIncome);
        }

        return totalIncome;
    }

    /**
     * 计算单个团队的总收入
     */
    private BigDecimal getTeamTotalSalary(
            Map<Long, TeamBillCycle> billCycleMap,
            Map<Long, List<TeamMemberTarget>> teamMemberTargetMap,
            Map<String, TeamPolicyManager> policyManagerMap,
            Long teamId) {

        TeamBillCycle billCycle = billCycleMap.get(teamId);
        if (billCycle == null) {
            return BigDecimal.ZERO;
        }

        List<TeamMemberTarget> targetList = teamMemberTargetMap.get(teamId);
        List<TeamBillMemberTarget> memberTargets = TeamBillCycleUtils.calculatorPolicyTarget(
                targetList, policyManagerMap.get(billCycle.getRegion()));

        return ownTotalSalary(memberTargets);
    }

    /**
     * 查询充值Teams汇总
     */
    private BdTeamSummaryCO.TeamSummaryItem queryRechargeTeamsSummary(Long userId) {
        BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();

        // 构建命令对象
        AppExtCommand cmd = new AppExtCommand();
        cmd.setReqUserId(userId);

        // 获取充值汇总数据
        RechargeSummaryVO rechargeSummary = rechargeUserService.getRechargeSummary(cmd);

        if (rechargeSummary == null) {
            item.setCount(0);
            item.setTotalIncome(BigDecimal.ZERO);
            return item;
        }

        item.setCount(rechargeSummary.getCount());
        item.setTotalIncome(rechargeSummary.getCurrentMonthRecharge());

        return item;
    }

    /**
     * 汇总成员工资
     */
    private BigDecimal ownTotalSalary(List<TeamBillMemberTarget> teamBillMemberTargets) {
        return teamBillMemberTargets.stream()
                .map(TeamBillMemberTarget::getTotalSalary)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .setScale(2, RoundingMode.DOWN);
    }
}
