package com.red.circle.other.infra.database.cache.service.cp.impl;

import com.alibaba.fastjson.JSON;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.infra.database.cache.key.user.UserKey;
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
import com.red.circle.other.infra.database.rds.entity.user.user.BaseInfo;
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
import com.red.circle.other.infra.database.rds.service.user.user.BaseInfoService;
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
import com.red.circle.other.inner.model.dto.user.CpSimpleUserProfileCO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * CP关系缓存服务实现.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheService {

    private final CpRelationshipService  cpRelationshipService;
    private final RedisService redisService;
    private final BaseInfoService baseInfoService;
    private final CpValueService cpValueService;


    private static final long CACHE_EXPIRE_SECONDS = 7200L;

    @Override
    public List<CpSimpleUserProfileCO> getUserCpList(Long userId) {
        String key = getKey(userId);
        
        String cacheData = redisService.getString(key);
        if (cacheData != null) {
            return JSON.parseArray(cacheData, CpSimpleUserProfileCO.class);
        }


        try {
            List<CpRelationship> cpRelationshipList = cpRelationshipService.getByUserId(userId);
            if (CollectionUtils.isEmpty(cpRelationshipList)) {
                redisService.setString(key, JSON.toJSONString(Collections.emptyList()), CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS);
                return Collections.emptyList();
            }

            // 批量获取CP用户信息
            Set<Long> cpUserIds = cpRelationshipList.stream()
                    .map(CpRelationship::getCpUserId)
                    .collect(Collectors.toSet());
            List<BaseInfo>  cpUserProfiles = baseInfoService.listByUserId(cpUserIds);
            Map<Long, BaseInfo> cpUserProfileMap = cpUserProfiles.stream()
                    .collect(Collectors.toMap(BaseInfo::getId, Function.identity()));
            BaseInfo baseInfo = baseInfoService.getById(userId);

            // 批量获取CP值
            Set<Long> cpValIds = cpRelationshipList.stream()
                    .map(CpRelationship::getCpValId)
                    .collect(Collectors.toSet());
            Map<Long, BigDecimal> cpValueMap = cpValueService.mapCpVal(cpValIds);

            // 组装CP列表
            List<CpSimpleUserProfileCO> cpList = cpRelationshipList.stream()
                    .map(cpRelationship -> {
                        BaseInfo cpUser = cpUserProfileMap.get(cpRelationship.getCpUserId());
                        if (cpUser == null) {
                            return null;
                        }

                        BigDecimal cpValue = cpValueMap.getOrDefault(cpRelationship.getCpValId(), BigDecimal.ZERO);
                        Long days = DateUtils.toDurationDays(cpRelationship.getCreateTime(), DateUtils.now());
                        String firstDay = cpRelationship.getCreateTime().toInstant()
                                .atZone(ZoneId.systemDefault()).toLocalDate().toString();

                        return new CpSimpleUserProfileCO()
                                .setMeUserId(baseInfo.getId())
                                .setMeAccount(baseInfo.getAccount())
                                .setMeUserAvatar(baseInfo.getUserAvatar())
                                .setMeUserNickname(baseInfo.getUserNickname())
                                .setCpUserId(cpUser.getId())
                                .setCpAccount(cpUser.getAccount())
                                .setCpUserAvatar(cpUser.getUserAvatar())
                                .setCpUserNickname(cpUser.getUserNickname())
                                .setCpValId(cpRelationship.getCpValId())
                                .setCpValue(cpValue)
                                .setCreateTime(cpRelationship.getCreateTime())
                                .setDays(days)
                                .setFirstDay(firstDay);
                    })
                    .filter(Objects::nonNull)
                    .sorted(Comparator.comparing(CpSimpleUserProfileCO::getCpValue).reversed()
                            .thenComparing(CpSimpleUserProfileCO::getCreateTime))
                    .toList();

            redisService.setString(key, JSON.toJSONString(cpList), CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS);
            return cpList;
        } catch (Exception e) {
            log.error("填充CP数据失败, userId={}", userId, e);
        }

        return Collections.emptyList();
    }

    private static String getKey(Long userId) {
        return UserKey.CP.getKey(userId);
    }

    @Override
    public void remove(List<Long> userIds) {
        userIds.forEach(userId -> {
            redisService.delete(getKey(userId));
        });
    }
}
