package com.red.circle.other.infra.database.rds.service.gift.impl;

import com.google.common.collect.Lists;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.gift.GiftConfigDAO;
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
import com.red.circle.other.inner.enums.material.GiftCurrencyType;
import com.red.circle.other.inner.enums.material.GiftSpecialEnum;
import com.red.circle.other.inner.enums.material.GiftTabEnum;
import com.red.circle.other.inner.model.cmd.sys.GiftQryCmd;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.NumUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 礼物信息 服务实现类.
 * </p>
 *
 * @author pengliang
 * @since 2020-06-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GiftConfigServiceImpl extends BaseServiceImpl<GiftConfigDAO, GiftConfig> implements
    GiftConfigService {

  @Override
  public GiftConfig getRandomCp(SysOriginPlatformEnum sysOrigin) {
    return Optional.ofNullable(query()
            .eq(GiftConfig::getGiftTab, GiftTabEnum.CP)
            .eq(GiftConfig::getSysOrigin, sysOrigin)
            .eq(GiftConfig::getDel, Boolean.FALSE)
            .last(PageConstant.DEFAULT_LIMIT)
            .list())
        .filter(CollectionUtils::isNotEmpty)
        .map(giftConfigs -> giftConfigs.get(NumUtils.randomBetween(0, giftConfigs.size() - 1)))
        .orElse(null);
  }

  @Override
  public void updateWeekStarSetting(SysOriginPlatformEnum sysOrigin, List<Long> gifts) {
    if (CollectionUtils.isEmpty(gifts)) {
      return;
    }

    List<GiftConfig> giftConfigs = query()
        .like(GiftConfig::getSpecial, GiftSpecialEnum.STAR.name())
        .eq(GiftConfig::getSysOrigin, sysOrigin)
        .list();

    if (CollectionUtils.isEmpty(giftConfigs)) {
      updateBatchById(addNewGiftsWeekStar(gifts));
      return;
    }

    updateBatchById(
        Stream.of(removeGiftsWeekStar(giftConfigs), addNewGiftsWeekStar(gifts))
            .flatMap(Collection::stream)
            .collect(Collectors.toList()));
  }

  private List<GiftConfig> removeGiftsWeekStar(List<GiftConfig> giftConfigs) {
    return giftConfigs.stream()
        .peek(giftConfig -> giftConfig.removeSpecial(GiftSpecialEnum.STAR.name()))
        .collect(Collectors.toList());
  }

  private List<GiftConfig> addNewGiftsWeekStar(List<Long> gifts) {
    List<GiftConfig> newGiftConfigs = query().in(GiftConfig::getId, gifts).list();
    if (CollectionUtils.isEmpty(newGiftConfigs)) {
      log.warn("添加周星礼物错误，没有找到相关数据:{}", gifts);
      return CollectionUtils.newArrayList();
    }
    return newGiftConfigs.stream()
        .peek(giftConfig -> giftConfig.addSpecial(GiftSpecialEnum.STAR.name()))
        .collect(Collectors.toList());
  }

  @Override
  public GiftConfig getCheapest(SysOriginPlatformEnum sysOrigin, GiftCurrencyType type) {
    return query()
        .eq(GiftConfig::getDel, Boolean.FALSE)
        .eq(GiftConfig::getSysOrigin, sysOrigin)
        .eq(GiftConfig::getType, type)
        .orderByAsc(GiftConfig::getGiftCandy)
        .last(PageConstant.LIMIT_ONE)
        .getOne();
  }

  @Override
  public List<GiftConfig> listByIds(Collection<Long> ids) {
    if (CollectionUtils.isEmpty(ids)) {
      return CollectionUtils.newArrayList();
    }
    return query()
        .in(GiftConfig::getId, ids)
        .orderByDesc(GiftConfig::getSort)
        .list();
  }

  @Override
  public List<GiftConfig> listSortAscCandyByIds(Collection<Long> ids) {
    if (CollectionUtils.isEmpty(ids)) {
      return null;
    }
    return query()
        .in(GiftConfig::getId, ids)
        .orderByAsc(GiftConfig::getGiftCandy)
        .list();
  }

  @Override
  public GiftConfig getEffectiveById(Long id) {
    return Optional.ofNullable(getById(id)).orElse(null);
  }

  @Override
  public Map<Long, GiftConfig> mapByIds(Set<Long> ids) {
    return CollectionUtils.isEmpty(ids)
        ? CollectionUtils.newHashMap()
        : Optional.ofNullable(
                query().in(GiftConfig::getId, ids).list()
            ).map(giftConfigInfos -> giftConfigInfos.stream()
                .collect(Collectors.toMap(GiftConfig::getId, v -> v)))
            .orElse(CollectionUtils.newHashMap());
  }

  @Override
  public List<GiftConfig> listEffectiveSysOriginGift(SysOriginPlatformEnum sysOrigin) {
    return query()
        .eq(GiftConfig::getSysOrigin, sysOrigin)
        .eq(GiftConfig::getDel, Boolean.FALSE)
        .orderByDesc(GiftConfig::getSort)
        .list();
  }

  @Override
  public void updateExclusiveNotInDown(List<Long> ids) {
    update()
        .set(GiftConfig::getDel, Boolean.TRUE)
        .notIn(GiftConfig::getId, ids)
        .eq(GiftConfig::getGiftTab, GiftTabEnum.EXCLUSIVE)
        .execute();
  }

  @Override
  public void updateExclusiveRecovery(List<Long> ids) {
    update()
        .set(GiftConfig::getDel, Boolean.FALSE)
        .in(GiftConfig::getId, ids)
        .eq(GiftConfig::getGiftTab, GiftTabEnum.EXCLUSIVE)
        .execute();
  }

  @Override
  public GiftConfig getByCode(String code) {
    return query()
        .eq(GiftConfig::getGiftCode, code)
        .last(PageConstant.LIMIT_ONE)
        .getOne();
  }

  @Override
  public List<GiftConfig> listBySysOrigin(String sysOrigin) {
    return query()
        .eq(GiftConfig::getSysOrigin, sysOrigin)
        .orderByDesc(GiftConfig::getGiftCandy)
        .list();
  }

  @Override
  public PageResult<GiftConfig> pageGiftInfo(GiftQryCmd giftQryCmd) {
    return query()
        .eq(Objects.nonNull(giftQryCmd.getGiftId()), GiftConfig::getId, giftQryCmd.getGiftId())
        .like(StringUtils.isNotBlank(giftQryCmd.getGiftName()), GiftConfig::getGiftName,
            giftQryCmd.getGiftName())
        .eq(StringUtils.isNotBlank(giftQryCmd.getSysOrigin()), GiftConfig::getSysOrigin,
            giftQryCmd.getSysOrigin())
        .eq(StringUtils.isNotBlank(giftQryCmd.getGiftTab()), GiftConfig::getGiftTab,
            giftQryCmd.getGiftTab())
        .eq(StringUtils.isNotBlank(giftQryCmd.getType()), GiftConfig::getType, giftQryCmd.getType())
        .like(StringUtils.isNotBlank(giftQryCmd.getRegion()), GiftConfig::getRegions,
            giftQryCmd.getRegion())
        .ge(Objects.nonNull(giftQryCmd.getStartCreateDate()), GiftConfig::getCreateTime,
            giftQryCmd.getStartCreateDate())
        .le(Objects.nonNull(giftQryCmd.getEndCreateDate()), GiftConfig::getCreateTime,
            giftQryCmd.getEndCreateDate())
        .eq(Objects.nonNull(giftQryCmd.getDel()), GiftConfig::getDel, giftQryCmd.getDel())
        .orderByDesc(giftQryCmd.checkCreateTimeDesc(), GiftConfig::getId)
        .orderByDesc(giftQryCmd.checkAmountDesc(), GiftConfig::getGiftCandy)
        .orderByDesc(giftQryCmd.checkSortDesc(), GiftConfig::getSort)
        .page(giftQryCmd.getPageQuery());
  }

  @Override
  public Boolean updateGift(GiftConfig giftConfig) {
    return update()
        .set(GiftConfig::getGiftPhoto, giftConfig.getGiftPhoto())
        .set(GiftConfig::getGiftName, giftConfig.getGiftName())
        .set(GiftConfig::getGiftSourceUrl, giftConfig.getGiftSourceUrl())
        .set(GiftConfig::getGiftCode, giftConfig.getGiftCode())
        .set(GiftConfig::getGiftCandy, giftConfig.getGiftCandy())
        .set(GiftConfig::getGiftIntegral, giftConfig.getGiftIntegral())
        .set(GiftConfig::getSpecial, giftConfig.getSpecial())
        .set(GiftConfig::getRegions, giftConfig.getRegions())
        .set(GiftConfig::getType, giftConfig.getType())
        .set(GiftConfig::getSort, giftConfig.getSort())
        .set(GiftConfig::getGiftTab, giftConfig.getGiftTab())
        .set(GiftConfig::getStandardId, giftConfig.getStandardId())
        .set(GiftConfig::getExpiredTime, giftConfig.getExpiredTime())
        .set(GiftConfig::getExplanationGift,
            Objects.nonNull(giftConfig.getExplanationGift()) ? giftConfig.getExplanationGift()
                : Boolean.FALSE)
        .set(GiftConfig::getUserId, giftConfig.getUserId())
        .eq(GiftConfig::getId, giftConfig.getId())
        .last(PageConstant.LIMIT_ONE)
        .execute();
  }

  @Override
  public Boolean switchDelStatus(Long id, Boolean status) {
    return update().set(GiftConfig::getDel, status)
        .eq(GiftConfig::getId, id)
        .execute();
  }

  @Override
  public List<GiftConfig> listByTab(String sysOrigin, String giftTab) {
    return Optional.ofNullable(query()
            .eq(GiftConfig::getSysOrigin, sysOrigin)
            .eq(GiftConfig::getGiftTab, giftTab)
            .eq(GiftConfig::getDel, Boolean.FALSE)
            .list())
        .orElse(Lists.newArrayList());
  }

  @Override
  public List<GiftConfig> listByTabV2(GiftQryCmd query) {
    return Optional.ofNullable(query()
            .eq(StringUtils.isNotBlank(query.getSysOrigin()), GiftConfig::getSysOrigin,
                query.getSysOrigin())
            .eq(StringUtils.isNotBlank(query.getGiftTab()), GiftConfig::getGiftTab,
                query.getGiftTab())
            .eq(GiftConfig::getDel, Boolean.TRUE)
            .orderByDesc(GiftConfig::getCreateTime)
            .list())
        .orElse(Lists.newArrayList());
  }

  @Override
  public List<GiftConfig> list(String sysOrigin) {
    return Optional.ofNullable(query()
            .eq(GiftConfig::getSysOrigin, sysOrigin)
            .eq(GiftConfig::getDel, Boolean.FALSE)
            .orderByDesc(GiftConfig::getCreateTime)
            .list())
        .orElse(Lists.newArrayList());
  }

  @Override
  public List<GiftConfig> getLuckyGiftByStandardId(Long standardId, String giftTab) {
    return Optional.ofNullable(query()
            .eq(GiftConfig::getGiftTab, giftTab)
            .eq(GiftConfig::getStandardId, standardId)
            .eq(GiftConfig::getDel, Boolean.FALSE)
            .last(PageConstant.MAX_LIMIT)
            .list())
        .orElse(Lists.newArrayList());
  }

  @Override
  public List<GiftConfig> listConfessionGifts(String sysOrigin) {
    return query()
        .eq(GiftConfig::getSysOrigin, sysOrigin)
        .eq(GiftConfig::getDel, Boolean.FALSE)
        .eq(GiftConfig::getExplanationGift, Boolean.TRUE)
        .orderByDesc(GiftConfig::getSort)
        .list();
  }

  @Override
  public List<GiftConfig> listByExpiredTime(Timestamp now) {
    return Optional.ofNullable(query()
            .eq(GiftConfig::getDel, Boolean.FALSE)
            .isNotNull(GiftConfig::getExpiredTime)
            .le(GiftConfig::getExpiredTime, now)
            .list())
        .orElse(Lists.newArrayList());
  }
}
