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

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.props.PropsVipActualEquityDAO;
import com.red.circle.other.infra.database.rds.entity.props.PropsVipActualEquity;
import com.red.circle.other.infra.database.rds.service.props.PropsVipActualEquityService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 用户所得贵族实际权益表 服务实现类.
 * </p>
 *
 * @author pengshigang
 * @since 2022-06-21
 */
@Service
public class PropsVipActualEquityServiceImpl extends
    BaseServiceImpl<PropsVipActualEquityDAO, PropsVipActualEquity> implements
    PropsVipActualEquityService {

  @Override
  public Set<Long> getActualEquityNotExpired(Long userId) {

    return Optional.ofNullable(
        query().select(PropsVipActualEquity::getPropsId)
            .gt(PropsVipActualEquity::getExpireTime, TimestampUtils.now())
            .eq(PropsVipActualEquity::getUserId, userId)
            .last(PageConstant.formatLimit(5))
            .list()
    ).map(actualEquities -> actualEquities.stream().map(PropsVipActualEquity::getPropsId)
        .filter(Objects::nonNull)
        .collect(Collectors.toSet())).orElse(CollectionUtils.newHashSet());
  }

  @Override
  public boolean existsNotExpiredPropsId(Long propsId) {
    if (Objects.isNull(propsId)) {
      return Boolean.FALSE;
    }
    return Optional.ofNullable(
            query().select(PropsVipActualEquity::getId)
                .gt(PropsVipActualEquity::getExpireTime, TimestampUtils.now())
                .eq(PropsVipActualEquity::getPropsId, propsId)
                .getOne()
        ).map(actualEquities -> Objects.nonNull(actualEquities.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public void save(Long userId, Long vipPropsId, Long days) {

    PropsVipActualEquity vipActualEquity = query()
        .eq(PropsVipActualEquity::getPropsId, vipPropsId)
        .eq(PropsVipActualEquity::getUserId, userId)
        .last(PageConstant.LIMIT_ONE)
        .getOne();

    if (Objects.isNull(vipActualEquity)) {

      save(new PropsVipActualEquity()
          .setId(IdWorkerUtils.getId())
          .setPropsId(vipPropsId)
          .setUserId(userId)
          .setExpireTime(TimestampUtils.nowPlusDays(days))
          .setCreateTime(TimestampUtils.now())
          .setUpdateTime(TimestampUtils.now())
          .setCreateUser(userId)
      );
      return;
    }

    vipActualEquity.setExpireTime(getExpireTime(days, vipActualEquity.getExpireTime()));
    updateSelectiveById(vipActualEquity);

  }

  private Timestamp getExpireTime(Long days, Timestamp time) {
    return Optional.ofNullable(time)
        .map(date -> TimestampUtils.expiredPlusDays(date, days.intValue()))
        .orElse(TimestampUtils.nowPlusDays(days));
  }

  @Override
  public PropsVipActualEquity getByPropsIdByUserId(Long userId, Long vipPropsId) {
    return query()
        .eq(PropsVipActualEquity::getPropsId, vipPropsId)
        .eq(PropsVipActualEquity::getUserId, userId)
        .last(PageConstant.LIMIT_ONE)
        .getOne();
  }

  @Override
  public void changeBelongUserId(Long acceptUserId, Long userId, Long propsId) {
    PropsVipActualEquity acceptPropsInfo = query()
        .eq(PropsVipActualEquity::getPropsId, propsId)
        .eq(PropsVipActualEquity::getUserId, acceptUserId)
        .last(PageConstant.LIMIT_ONE)
        .getOne();
    if (Objects.isNull(acceptPropsInfo)) {
      update().set(PropsVipActualEquity::getUserId, acceptUserId)
          .eq(PropsVipActualEquity::getUserId, userId)
          .eq(PropsVipActualEquity::getPropsId, propsId)
          .last(PageConstant.LIMIT_ONE)
          .execute();
    } else {

      PropsVipActualEquity propsInfo = query()
          .eq(PropsVipActualEquity::getPropsId, propsId)
          .eq(PropsVipActualEquity::getUserId, userId)
          .last(PageConstant.LIMIT_ONE)
          .getOne();

      Long milliSecond = TimestampUtils.expiredIntervalMillisecond(acceptPropsInfo.getExpireTime(),
          TimestampUtils.now());
      if (milliSecond <= 0) {
        update().set(PropsVipActualEquity::getExpireTime,
                TimestampUtils.dateTimePlusSeconds(acceptPropsInfo.getExpireTime(),
                    TimestampUtils.expiredIntervalSecond(TimestampUtils.now(),
                        propsInfo.getExpireTime())))
            .eq(PropsVipActualEquity::getUserId, acceptUserId)
            .eq(PropsVipActualEquity::getPropsId, propsId)
            .last(PageConstant.LIMIT_ONE)
            .execute();
      } else {
        update().set(PropsVipActualEquity::getExpireTime, propsInfo.getExpireTime())
            .eq(PropsVipActualEquity::getUserId, acceptUserId)
            .eq(PropsVipActualEquity::getPropsId, propsId)
            .last(PageConstant.LIMIT_ONE)
            .execute();

      }

      update().set(PropsVipActualEquity::getExpireTime, TimestampUtils.now())
          .eq(PropsVipActualEquity::getUserId, userId)
          .eq(PropsVipActualEquity::getPropsId, propsId)
          .last(PageConstant.LIMIT_ONE)
          .execute();
    }


  }
}
