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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.app.command.activity.*;
import com.red.circle.other.app.dto.clientobject.activity.ActivityAgentAnchorContentCO;
import com.red.circle.other.app.dto.clientobject.activity.GiftRankCO;
import com.red.circle.other.app.dto.clientobject.activity.GiftRankUserCO;
import com.red.circle.other.app.dto.clientobject.activity.ResultGiftRankUserCO;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.domain.model.user.ability.RegionConfig;
import com.red.circle.other.infra.database.mongo.dto.query.GiftGiveRunningWaterQuery;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftAcceptUser;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftGiveRunningWater;
import com.red.circle.other.infra.database.mongo.service.gift.GiftGiveRunningWaterService;
import com.red.circle.other.infra.database.rds.entity.sys.EnumConfig;
import com.red.circle.other.infra.database.rds.service.sys.EnumConfigService;
import com.red.circle.other.infra.database.rds.service.user.user.BaseInfoService;
import com.red.circle.other.infra.utils.ZonedDateTimeUtils;
import com.red.circle.other.inner.asserts.ActivityErrorCode;
import com.red.circle.other.inner.endpoint.user.region.UserRegionClient;
import com.red.circle.other.inner.enums.task.ReceiveStatusEnum;
import com.red.circle.other.inner.model.cmd.sys.SysEnumConfigQryCmd;
import com.red.circle.other.inner.model.dto.activity.props.ActivityRewardProps;
import com.red.circle.other.inner.model.dto.pet.UserBaseInfoDTO;
import com.red.circle.other.inner.model.dto.user.reigon.RegionConfigDTO;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 礼物排行
 *
 * @author pengshigang on 2023/2/13
 */
@Service
@RequiredArgsConstructor
public class ActivityGiveRankServiceImpl implements ActivityGiveRankService {

    private final ActivityAgentAnchorReceiveCmdExe activityAgentAnchorReceiveCmdExe;

    private final GiftGiveRunningWaterService giftGiveRunningWaterService;
    private final BaseInfoService baseInfoService;
    private final EnumConfigService enumConfigService;
    private final UserRegionGateway userRegionGateway;


    @Override
    public GiftRankCO giftRankByRoom(AppExtCommand cmd) {
        //当下活动时间   13  14  和总计 一共需要返回三个列表
        String reqZoneId = cmd.getReqZoneId();
//        //当前时间是
//        String regionByZone = ZonedDateTimeUtils.getRegionByZone(reqZoneId);
        RegionConfig regionConfig = userRegionGateway.getRegionConfigByUserId(cmd.requiredReqUserId());
        String codes = regionConfig.getCountryCodes();
        //默认
        String code = "IN";
        if (StringUtils.isNotEmpty(code)) {
            if (codes.contains(",")) {
                code = codes.split(",")[0];
            } else {
                code = codes;
            }
        }
        //当前时间是
//        String regionByZone = ZonedDateTimeUtils.getTimeZonesData(code);

        //获取配置
        SysEnumConfigQryCmd configQuery = new SysEnumConfigQryCmd();
        configQuery.setName("");
        EnumConfig enumConfig = enumConfigService.getByEnumConfig("ROOM_RANK", cmd.getReqSysOrigin().getOrigin());
        ResponseAssert.isTrue(ActivityErrorCode.ACTIVITY_NOT_CONFIGURED_ERROR,
                !Objects.isNull(enumConfig));
        JSONArray objects = JSONObject.parseArray(enumConfig.getVal());
        String roomId = null;
        for (Object obj : objects) {
            JSONObject record = (JSONObject) obj;
            if (record.get("region").equals(code)) {
//            if (record.get("region").equals(regionByZone)) {
                roomId = (String) record.get("roomId");
                break;
            }
        }
        ResponseAssert.isTrue(ActivityErrorCode.ACTIVITY_ROOM_NOT_EXIST,
                !Objects.isNull(roomId));
//        String roomId = switch (regionByZone) {
//            case "CN" -> "1895100794160066562";
//            case "IN" -> "1894752301885206529";
//            default -> "1895100794160066562";
//        };
        ZonedDateTime currentTime = ZonedDateTime.now(java.time.ZoneId.of(reqZoneId));
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //印度测试房间 1895100794160066562
        //中国 测试房间 1894752301885206529
        //获取三月10  11 两天,截止时间是 11号的23点59分59秒 根据不同的地区获取不同的房间,返回不同的结束时间

        // 获取三月 10 号和 11 号，截止时间是 11 号的 23 点 59 分 59 秒
        //获取时间配置的开始时间和结束时间
        EnumConfig enumTimeConfig = enumConfigService.getByEnumConfig("ROOM_RANK_TIME", cmd.getReqSysOrigin().getOrigin());
        ResponseAssert.isTrue(ActivityErrorCode.ACTIVITY_NOT_CONFIGURED_ERROR,
                !Objects.isNull(enumTimeConfig));
        String rangeDate = enumTimeConfig.getVal();
        String[] split = rangeDate.split(",");
        String startTime = split[0];
        String endTime = split[1];


        LocalDate startDate = LocalDate.of(currentTime.getYear(), currentTime.getMonth(), Integer.parseInt(startTime));
        long startMilli = startDate.atStartOfDay(ZoneId.of(reqZoneId)).toInstant().toEpochMilli();
        LocalDate endDate = LocalDate.of(currentTime.getYear(), currentTime.getMonth(), Integer.parseInt(endTime));
        LocalDateTime endDateTime = endDate.atTime(23, 59, 59);
        long endMilli = endDateTime.atZone(ZoneId.of(reqZoneId)).toInstant().toEpochMilli();
        //这个是返回客户端的分地区结束时间
        GiftGiveRunningWaterQuery query = new GiftGiveRunningWaterQuery();
        query.setOriginId(roomId);
        query.setStartTime(startDate.atStartOfDay().atZone(ZoneId.of(reqZoneId)).toInstant().toEpochMilli());
        //这个是查询数据库的结束时间
        query.setEndTime(endMilli);
        query.setEndTime(startMilli);
        query.setEndTime(endMilli);
//        query.setLimit(50);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<GiftGiveRunningWater> list = giftGiveRunningWaterService.list(query);
        // 直接在 Stream 流中处理并分组
        Map<String, List<GiftGiveRunningWater>> groupedMap = list.stream()
                .collect(Collectors.groupingBy(item -> sdf.format(item.getCreateTime())));

        // 补齐缺失日期的空列表
        LocalDate currentDate = startDate;
        while (!currentDate.isAfter(endDate)) {
            String dateStr = sdf.format(Date.from(currentDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
            groupedMap.putIfAbsent(dateStr, new ArrayList<>());
            currentDate = currentDate.plusDays(1);
        }
        Map<String, List<GiftGiveRunningWater>> sortedMap = new TreeMap<>(groupedMap);
        // 计算 然后排序
        //获取对应的用户信息
        Set<Long> userIds = new HashSet<>();
        list.forEach(item -> userIds.addAll(item.getAcceptUsers().stream().map(GiftAcceptUser::getAcceptUserId).collect(Collectors.toSet())));
        Map<Long, UserBaseInfoDTO> longUserBaseInfoDTOMap = baseInfoService.mapUserBaseInfoDTO(userIds);
        List<ResultGiftRankUserCO> resultList = Lists.newArrayList();
        for (Map.Entry<String, List<GiftGiveRunningWater>> entry : sortedMap.entrySet()) {
            ResultGiftRankUserCO resultUser = new ResultGiftRankUserCO();
            resultUser.setDate(entry.getKey());

            String date = entry.getKey();
            List<GiftGiveRunningWater> groupList = entry.getValue();

            // 收集所有 GiftAcceptUser 对象
            List<GiftAcceptUser> allAcceptUsers = new ArrayList<>();
            groupList.forEach(item -> allAcceptUsers.addAll(item.getAcceptUsers()));

            // 合并相同 acceptUserId 的 GiftAcceptUser 对象
            Map<Long, GiftRankUserCO> mergedMap = new HashMap<>();
            for (GiftAcceptUser acceptUser : allAcceptUsers) {
                Long acceptUserId = acceptUser.getAcceptUserId();
                UserBaseInfoDTO info = longUserBaseInfoDTOMap.get(acceptUserId);
                if (mergedMap.containsKey(acceptUserId)) {
                    GiftRankUserCO existingUser = mergedMap.get(acceptUserId);
                    existingUser.setAcceptAmount(existingUser.getAcceptAmount().add(acceptUser.getTargetAmount()));
                } else {
                    mergedMap.put(acceptUserId, GiftRankUserCO.builder()
                            .acceptUserId(acceptUserId)
                            .acceptUserName(info.getUserNickname())
                            .userAvatar(info.getUserAvatar())
                            //特殊处理
                            .acceptAmount(acceptUser.getTargetAmount())
                            .acceptUserId(acceptUserId)
                            .build());

                }
            }

            // 将合并后的结果转换为列表
            List<GiftRankUserCO> mergedList = new ArrayList<>(mergedMap.values());

            // 按 acceptAmount 降序排序
            mergedList.sort((u1, u2) -> u2.getAcceptAmount().compareTo(u1.getAcceptAmount()));

            // 设置到 GiftRankUserCO 对象中
            resultUser.setList(mergedList);
            resultList.add(resultUser);
            //新增一个总计

//
//            System.out.println("日期: " + date + ", 数量: " + groupList.size());
//            for (GiftGiveRunningWater item : groupList) {
//                System.out.println("  - " + item.getCreateTime());
//            }
        }
        ResultGiftRankUserCO totalRank = new ResultGiftRankUserCO();
        totalRank.setDate("总计");
//        totalRank.setList(new ArrayList<>());

        // 存储每个用户的总计金额
        Map<Long, BigDecimal> userTotalAmountMap = new HashMap<>();

        for (ResultGiftRankUserCO rank : resultList) {
            List<GiftRankUserCO> userList = rank.getList();
            for (GiftRankUserCO user : userList) {
                Long userId = user.getAcceptUserId();
                BigDecimal amount = user.getAcceptAmount();
                userTotalAmountMap.put(userId, userTotalAmountMap.getOrDefault(userId, BigDecimal.ZERO).add(amount));
            }
        }

        // 将汇总结果转换为 GiftRankUserCO 列表
        List<GiftRankUserCO> totalUserList = userTotalAmountMap.entrySet().stream()
                .map(entry -> {
                    UserBaseInfoDTO info = longUserBaseInfoDTOMap.get(entry.getKey());
                    return GiftRankUserCO
                            .builder()
                            .acceptUserId(entry.getKey())
                            .acceptAmount(entry.getValue())
                            .acceptUserName(info.getUserNickname())
                            .userAvatar(info.getUserAvatar())
                            .build();
                })
                .sorted((u1, u2) -> u2.getAcceptAmount().compareTo(u1.getAcceptAmount()))
                .limit(50)
                .collect(Collectors.toList());

        totalRank.setList(totalUserList);
        resultList.add(totalRank);


        for (ResultGiftRankUserCO resultGiftRankUserCO : resultList) {
            for (int i = 0; i < resultGiftRankUserCO.getList().size(); i++) {

                //判断是否有当前用户 有的话 单独拿出来,并计算上一个索引的金额和当前金额的差值
                GiftRankUserCO user = resultGiftRankUserCO.getList().get(i);
                if (user.getAcceptUserId().equals(cmd.getReqUserId())) {
                    // 计算上一个索引的金额和当前金额的差值
                    if (i > 0) {
                        GiftRankUserCO previousUser = resultGiftRankUserCO.getList().get(i - 1);
                        BigDecimal difference = previousUser.getAcceptAmount().subtract(user.getAcceptAmount());
                        user.setDistance(difference);
                    } else {
                        user.setDistance(new BigDecimal(0));
                    }
                    resultGiftRankUserCO.setCurrentUser(user);
                }
            }
        }
        GiftRankCO build = GiftRankCO.builder()
                .endTime(endMilli)
                .list(resultList)
                .build();

        String formattedTime = currentTime.format(formatter);
        System.out.println(formattedTime);

        System.out.println(reqZoneId);
        return build;


    }
}
