package edu.whut.infrastructure.adapter.repository;

import edu.whut.domain.activity.adapter.repository.IActivityRepository;
import edu.whut.domain.activity.model.entity.UserGroupBuyOrderDetailEntity;
import edu.whut.domain.activity.model.valobj.*;
import edu.whut.infrastructure.dao.*;
import edu.whut.infrastructure.dao.po.*;
import edu.whut.infrastructure.dcc.DCCService;
import edu.whut.infrastructure.redis.IRedisService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBitSet;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 活动仓储
 */
@Repository
@RequiredArgsConstructor
@Slf4j
public class ActivityRepository extends AbstractRepository implements IActivityRepository {

    private final IGroupBuyActivityDao groupBuyActivityDao;

    private final IGroupBuyDiscountDao groupBuyDiscountDao;

    private final ISkuDao skuDao;

    private final ISCSkuActivityDao skuActivityDao;

    private final IRedisService redisService;

    private final DCCService dccService;

    private final IGroupBuyOrderDao groupBuyOrderDao;

    private final IGroupBuyOrderListDao groupBuyOrderListDao;

    @Override
    public GroupBuyActivityDiscountVO queryGroupBuyActivityDiscountVO(Long activityId) {
        // 优先从缓存获取&写缓存，注意如果实现了后台配置，在更新时要更库，删缓存。
        // TODO:数据更新时更库，删缓存还未实现
        GroupBuyActivity groupBuyActivityRes = getFromCacheOrDb(GroupBuyActivity.cacheRedisKey(activityId),
                () -> groupBuyActivityDao.queryValidGroupBuyActivityId(activityId));
        if (null == groupBuyActivityRes) return null;

        String discountId = groupBuyActivityRes.getDiscountId();

        // 优先从缓存获取&写缓存
        GroupBuyDiscount groupBuyDiscountRes = getFromCacheOrDb(GroupBuyDiscount.cacheRedisKey(discountId),
                () -> groupBuyDiscountDao.queryGroupBuyActivityDiscountByDiscountId(discountId));
        if (null == groupBuyDiscountRes) return null;

        GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = GroupBuyActivityDiscountVO.GroupBuyDiscount.builder()
                .discountName(groupBuyDiscountRes.getDiscountName())
                .discountDesc(groupBuyDiscountRes.getDiscountDesc())
                .discountType(DiscountTypeEnum.get(groupBuyDiscountRes.getDiscountType()))
                .marketPlan(groupBuyDiscountRes.getMarketPlan())
                .marketExpr(groupBuyDiscountRes.getMarketExpr())
                .tagId(groupBuyDiscountRes.getTagId())
                .build();

        return GroupBuyActivityDiscountVO.builder()
                .activityId(groupBuyActivityRes.getActivityId())
                .activityName(groupBuyActivityRes.getActivityName())
                .groupBuyDiscount(groupBuyDiscount)
                .groupType(groupBuyActivityRes.getGroupType())
                .takeLimitCount(groupBuyActivityRes.getTakeLimitCount())
                .target(groupBuyActivityRes.getTarget())
                .validTime(groupBuyActivityRes.getValidTime())
                .status(groupBuyActivityRes.getStatus())
                .startTime(groupBuyActivityRes.getStartTime())
                .endTime(groupBuyActivityRes.getEndTime())
                .tagId(groupBuyActivityRes.getTagId())
                .tagScope(groupBuyActivityRes.getTagScope())
                .build();
    }

    @Override
    public SkuVO querySkuByGoodsId(String goodsId) {
        Sku sku = skuDao.querySkuByGoodsId(goodsId);
        if (null == sku) return null;
        return SkuVO.builder()
                .goodsId(sku.getGoodsId())
                .goodsName(sku.getGoodsName())
                .originalPrice(sku.getOriginalPrice())
                .build();
    }

    @Override
    public SCSkuActivityVO querySCSkuActivityBySCGoodsId(String source, String channel, String goodsId) {
        SCSkuActivity scSkuActivityReq = new SCSkuActivity();
        scSkuActivityReq.setSource(source);
        scSkuActivityReq.setChannel(channel);
        scSkuActivityReq.setGoodsId(goodsId);

        SCSkuActivity scSkuActivity = skuActivityDao.querySCSkuActivityBySCGoodsId(scSkuActivityReq);
        if (null == scSkuActivity) return null;

        return SCSkuActivityVO.builder()
                .source(scSkuActivity.getSource())
                .chanel(scSkuActivity.getChannel())
                .activityId(scSkuActivity.getActivityId())
                .goodsId(scSkuActivity.getGoodsId())
                .build();
    }

    @Override
    public boolean isTagCrowdRange(String userId, String tagId) {
        //根据标签id获取对应位图
        RBitSet bitSet = redisService.getBitSet(tagId);
        if (!bitSet.isExists()) {
            //「如果后台没配置标签，默认所有用户都在优惠范围」。
            return true;
        }
        // 判断用户是否在优惠人群中，仅在名单范围内返回true
        return bitSet.get(redisService.getIndexFromUserId(userId));
    }

    @Override
    public boolean downgradeSwitch() {
        return dccService.isDowngradeSwitch();
    }

    @Override
    public boolean cutRange(String userId) {
        return dccService.isCutRange(userId);
    }

    public List<UserGroupBuyOrderDetailEntity> listRandomDetails(Long activityId, int randomCount) {


        if (randomCount <= 0) {
            return Collections.emptyList();
        }

        // 直接 DAO 调用，省掉 queryOrderLists
        GroupBuyOrderList req = new GroupBuyOrderList();
        req.setActivityId(activityId);
        req.setCount(randomCount);
        log.info("Built GroupBuyOrderList req: {}", req);
        List<GroupBuyOrderList> raw = Optional.ofNullable(
                        groupBuyOrderListDao.queryInProgressUserGroupBuyOrderDetailListByRandom(req))
                .orElse(Collections.emptyList());

        log.info("Raw result list ({} items): {}", raw.size(), raw);
        return raw.isEmpty() ? Collections.emptyList() : buildUserDetails(raw);
    }

    /**
     * 核心：把 DAO 返回的 List<GroupBuyOrderList>
     * 转成 List<UserGroupBuyOrderDetailEntity>
     */
    private List<UserGroupBuyOrderDetailEntity> buildUserDetails(List<GroupBuyOrderList> list) {
        if (list.isEmpty()) {
            return Collections.emptyList();
        }
        // 1. 收集所有 teamId
        Set<String> teamIds = list.stream()
                .map(GroupBuyOrderList::getTeamId)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());
        if (teamIds.isEmpty()) {
            return Collections.emptyList();
        }
        // 2. 一次性查队伍详情
        Map<String, GroupBuyOrder> orderMap = groupBuyOrderDao
                .queryGroupBuyProgressByTeamIds(teamIds).stream()
                .collect(Collectors.toMap(
                        GroupBuyOrder::getTeamId, Function.identity()
                ));
        // 3. 组装 DTO
        return list.stream()
                .map(item -> {
                    GroupBuyOrder order = orderMap.get(item.getTeamId());
                    if (order == null) {
                        return null;
                    }
                    return UserGroupBuyOrderDetailEntity.builder()
                            .userId         (item.getUserId())
                            .teamId         (order.getTeamId())
                            .activityId     (order.getActivityId())
                            .targetCount    (order.getTargetCount())
                            .completeCount  (order.getCompleteCount())
                            .lockCount      (order.getLockCount())
                            .validStartTime (order.getValidStartTime())
                            .validEndTime   (order.getValidEndTime())
                            .outTradeNo     (item.getOutTradeNo())
                            .build();
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    public TeamStatisticVO queryTeamStatisticByActivityId(Long activityId) {
        // 1. 根据活动ID查询所有拼团队伍id
        List<String> teamIds = groupBuyOrderDao.queryActiveTeamIdsByActivityId(activityId);
        if(null==teamIds || teamIds.isEmpty())
            return new TeamStatisticVO(0, 0, 0,0);
        Set<String> teamIdSet = new HashSet<>(teamIds);

        // 2. 统计数据
        Integer allTeamCount = groupBuyOrderDao.queryAllTeamCount(teamIdSet);  //该活动下的总拼团数
        Integer allTeamCompleteCount = groupBuyOrderDao.queryAllTeamCompleteCount(teamIdSet);  //该活动下已完成的拼团数
        Integer allTeamUserCount = groupBuyOrderDao.queryAllUserCount(teamIdSet);     //该活动下累计参与拼团人数
        Integer inTeamUserCount = groupBuyOrderDao.queryInUserCount(teamIdSet);      //该活动下在拼人数

        // 3. 构建对象
        return TeamStatisticVO.builder()
                .allTeamCount(allTeamCount)
                .allTeamCompleteCount(allTeamCompleteCount)
                .allTeamUserCount(allTeamUserCount)
                .inTeamUserCount(inTeamUserCount)
                .build();
    }

}
