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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.app.command.task.CheckInExe;
import com.red.circle.other.app.command.task.query.CheckInLotteryQryExe;
import com.red.circle.other.app.command.task.query.CheckInRewardQryExe;
import com.red.circle.other.app.common.props.SingleGroupRewardPoolCommon;
import com.red.circle.other.app.dto.clientobject.activity.ActivityResourceCO;
import com.red.circle.other.app.dto.clientobject.task.CheckInRewardListCO;
import com.red.circle.other.app.dto.cmd.task.CheckInRewardCmd;
import com.red.circle.other.infra.database.cache.service.other.CheckInCacheService;
import com.red.circle.other.infra.database.rds.entity.props.PropsCommodityStore;
import com.red.circle.other.infra.database.rds.service.props.PropsCommodityStoreService;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.model.dto.activity.props.ActivityRewardPropsDTO;
import com.red.circle.other.inner.endpoint.material.props.PropsNobleVipClient;
import com.red.circle.other.inner.model.dto.material.props.NobleVipAbility;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.parse.DataTypeUtils;
import com.red.circle.tool.core.tuple.PennyAmount;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.dto.VipGiveawayGoldRecordDTO;
import com.red.circle.wallet.inner.model.dto.WalletGoldAssetRecordDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 打卡服务实现.
 *
 * @author pengliang on 2020/11/27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CheckInServiceImpl implements CheckInService {

  private final CheckInExe checkInExe;
  private final CheckInRewardQryExe checkInRewardQryExe;
  private final CheckInCacheService checkInCacheService;
  private final CheckInLotteryQryExe checkInLotteryQryExe;
  private final SingleGroupRewardPoolCommon singleGroupRewardPoolCommon;
  private final WalletGoldClient walletGoldClient;
  private final PropsNobleVipClient propsNobleVipClient;
  private final PropsCommodityStoreService propsCommodityStoreService;


  @Override
  public List<ActivityRewardPropsDTO> listRewardPool(AppExtCommand cmd) {
    return singleGroupRewardPoolCommon
        .listRewardProps(cmd.getReqSysOrigin().getOrigin(), PropsActivityTypeEnum.DAILY_REGISTER);
  }

  @Override
  public Boolean checkToday(AppExtCommand cmd, String dailyKey) {
    return checkInCacheService.checkDailyCheckIn(cmd.getReqUserId(), dailyKey);
  }

  @Override
  public ActivityRewardPropsDTO lottery(AppExtCommand cmd) {
    return checkInLotteryQryExe.execute(cmd);
  }

  @Override
  public CheckInRewardListCO listReward(AppExtCommand cmd, PropsActivityTypeEnum activityType) {
    CheckInRewardListCO checkInRewardListCO = checkInRewardQryExe.execute(cmd, activityType);
    List<ActivityResourceCO> rewards  = checkInRewardListCO.getRewards();
    rewards.forEach(p->{
      if (p.getPropsGroup() != null){
        List<ActivityRewardPropsDTO> activityRewardProps = p.getPropsGroup().getActivityRewardProps();
        activityRewardProps.forEach(q->{
          if ("GOLD".equals(q.getType())){
            q.setCover("https://media.haiyihy.com/task/rw/lottery-gold.png");
            q.setQuantity(q.getAmount().intValue());
          }
        });
        p.getPropsGroup().setActivityRewardProps(activityRewardProps);
      }
    });
    return checkInRewardListCO;
  }

  @Override
  public Integer receive(CheckInRewardCmd cmd) {
    return checkInExe.execute(cmd);
  }

  @Override
  public List<VipGiveawayGoldRecordDTO> getLatestVipGiveawayRecords(AppExtCommand cmd) {
    Long userId = cmd.getReqUserId();
    Integer limit = 1; // 默认查询1条
    
    // 1. 调用wallet客户端查询VIP赠送记录（仅包含基础record信息）
    ResultResponse<List<WalletGoldAssetRecordDTO>> response = 
        walletGoldClient.getLatestVipGiveawayRecords(userId, limit);

    List<WalletGoldAssetRecordDTO> body = response.getBody();
    if (CollectionUtils.isEmpty(body)) {
      return CollectionUtils.newArrayList();
    }

    // 过滤出 createTime 是当天的记录
    List<WalletGoldAssetRecordDTO> records = body.stream()
            .filter(record -> {
              if (record.getCreateTime() == null) {
                return false;
              }
              LocalDateTime createDateTime = record.getCreateTime().toLocalDateTime();
              LocalDate createDate = createDateTime.toLocalDate();
              LocalDate now = LocalDate.now();
              return createDate.equals(now) || createDate.equals(now.minusDays(1));
            })
            .toList();
    if (CollectionUtils.isEmpty(body)) {
      return CollectionUtils.newArrayList();
    }

    // 2. 收集所有eventId (商品ID)
    Set<Long> commodityIds = records.stream()
        .map(WalletGoldAssetRecordDTO::getEventId)
        .filter(StringUtils::isNotBlank)
        .map(DataTypeUtils::toLong)
        .filter(Objects::nonNull)
        .collect(Collectors.toSet());
    
    if (CollectionUtils.isEmpty(commodityIds)) {
      return convertToVipGiveawayRecords(records, CollectionUtils.newHashMap());
    }
    
    // 3. 查询PropsCommodityStore获取sourceId
    LambdaQueryWrapper<PropsCommodityStore> queryWrapper = 
        Wrappers.<PropsCommodityStore>lambdaQuery()
            .in(PropsCommodityStore::getId, commodityIds);
    List<PropsCommodityStore> commodityStores = propsCommodityStoreService.list(queryWrapper);
    
    // 构建 commodityId -> sourceId 映射
    Map<Long, Long> commodityToSourceIdMap = commodityStores.stream()
        .collect(Collectors.toMap(
            PropsCommodityStore::getId, 
            PropsCommodityStore::getSourceId,
            (v1, v2) -> v1
        ));
    
    // 4. 收集所有VIP sourceId
    Set<Long> vipSourceIds = commodityToSourceIdMap.values().stream()
        .filter(Objects::nonNull)
        .collect(Collectors.toSet());
    
    // 5. 批量查询VIP信息
    Map<Long, NobleVipAbility> vipAbilityMap = CollectionUtils.newHashMap();
    if (CollectionUtils.isNotEmpty(vipSourceIds)) {
      try {
        ResultResponse<Map<Long, NobleVipAbility>> vipResponse = 
            propsNobleVipClient.mapAbilityByIds(vipSourceIds);
        if (Objects.nonNull(vipResponse) && vipResponse.checkSuccess() &&
            Objects.nonNull(vipResponse.getBody())) {
          vipAbilityMap = vipResponse.getBody();
        }
      } catch (Exception e) {
        log.error("查询VIP信息失败, userId={}", userId, e);
      }
    }
    
    // 6. 组装返回数据（record信息 + VIP信息）
    Map<Long, Long> finalCommodityToSourceIdMap = commodityToSourceIdMap;
    Map<Long, NobleVipAbility> finalVipAbilityMap = vipAbilityMap;
    
    return records.stream()
        .map(record -> {
          VipGiveawayGoldRecordDTO dto = new VipGiveawayGoldRecordDTO()
              .setId(record.getId())
              .setSysOrigin(record.getSysOrigin())
              .setUserId(record.getUserId())
              .setPennyAmount(record.getPennyAmount())
              .setAmount(PennyAmount.ofPenny(record.getPennyAmount()).getDollarAmount())
              .setPennyBalance(record.getPennyBalance())
              .setType(record.getType())
              .setEventType(record.getEventType())
              .setEventDesc(record.getEventDesc())
              .setEventId(record.getEventId())
              .setOpUserType(record.getOpUserType())
              .setCreateTime(record.getCreateTime())
              .setUpdateTime(record.getUpdateTime());
          
          // 设置VIP信息
          if (StringUtils.isNotBlank(record.getEventId())) {
            Long commodityId = DataTypeUtils.toLong(record.getEventId());
            if (Objects.nonNull(commodityId)) {
              Long sourceId = finalCommodityToSourceIdMap.get(commodityId);
              if (Objects.nonNull(sourceId)) {
                NobleVipAbility vipAbility = finalVipAbilityMap.get(sourceId);
                if (Objects.nonNull(vipAbility)) {
                  dto.setVipType(vipAbility.vipType())
                     .setVipLevel(vipAbility.vipLevel())
                     .setLoginRewardsAmount(vipAbility.loginRewardsAmount());
                }
              }
            }
          }
          
          return dto;
        })
        .collect(Collectors.toList());
  }
  
  private List<VipGiveawayGoldRecordDTO> convertToVipGiveawayRecords(
      List<WalletGoldAssetRecordDTO> records, 
      Map<Long, NobleVipAbility> vipAbilityMap) {
    return records.stream()
        .map(record -> new VipGiveawayGoldRecordDTO()
            .setId(record.getId())
            .setSysOrigin(record.getSysOrigin())
            .setUserId(record.getUserId())
            .setPennyAmount(record.getPennyAmount())
            .setAmount(PennyAmount.ofPenny(record.getPennyAmount()).getDollarAmount())
            .setPennyBalance(record.getPennyBalance())
            .setType(record.getType())
            .setEventType(record.getEventType())
            .setEventDesc(record.getEventDesc())
            .setEventId(record.getEventId())
            .setOpUserType(record.getOpUserType())
            .setCreateTime(record.getCreateTime())
            .setUpdateTime(record.getUpdateTime())
        )
        .collect(Collectors.toList());
  }

}
