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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.convertor.MybatisConvertor;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.dynamic.DynamicContentDAO;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicContent;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicContentService;
import com.red.circle.other.inner.model.cmd.dynamic.DelDynamicContentCmd;
import com.red.circle.other.inner.model.cmd.dynamic.DynamicContentQryCmd;
import com.red.circle.other.inner.model.dto.dynamic.PageDynamicContentDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;

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 lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 动态-朋友圈内容表 服务实现类.
 * </p>
 *
 * @author pengshigang
 * @since 2022-04-11
 */
@Service
@RequiredArgsConstructor
public class DynamicContentServiceImpl extends
    BaseServiceImpl<DynamicContentDAO, DynamicContent> implements DynamicContentService {

  private final DynamicContentDAO dynamicContentDAO;

  @Override
  public Map<Long, DynamicContent> mapByIds(Collection<Long> ids) {
    if (CollectionUtils.isEmpty(ids)) {
      return Maps.newHashMap();
    }
    return Optional.ofNullable(
            query().in(DynamicContent::getId, ids)
                .eq(DynamicContent::getDel, Boolean.FALSE)
                .last(PageConstant.formatLimit(ids.size()))
                .list()
        ).map(contents -> contents.stream().collect(Collectors.toMap(DynamicContent::getId, v -> v)))
        .orElse(Maps.newHashMap());
  }

  @Override
  public List<DynamicContent> pageByTimeDesc(Integer pageNumber, String region, String sysOrigin) {

    if (Objects.isNull(pageNumber) || pageNumber < 1) {
      pageNumber = 1;
    }

    return Optional.ofNullable(query()
            .eq(DynamicContent::getDel, Boolean.FALSE)
            .eq(DynamicContent::getSysOrigin, sysOrigin)
            .eq(DynamicContent::getRegion, region)
            .orderByDesc(DynamicContent::getCreateTime)
            .last(getPageSql(pageNumber))
            .list())
        .orElse(Lists.newArrayList());
  }

  @Override
  public List<DynamicContent> pageByTimeDesc(Integer pageNumber, Long userId) {
    if (Objects.isNull(pageNumber) || pageNumber < 1) {
      pageNumber = 1;
    }

    return query()
        .eq(DynamicContent::getDel, Boolean.FALSE)
        .eq(DynamicContent::getCreateUser, userId)
        .orderByDesc(DynamicContent::getCreateTime)
        .last(getPageSql(pageNumber))
        .list();
  }

  @Override
  public List<DynamicContent> pageByTimeDesc(Long tagId, Integer pageNumber) {

    if (Objects.isNull(pageNumber) || pageNumber < 1) {
      pageNumber = 1;
    }

    return query()
        .eq(DynamicContent::getTagId, tagId)
        .eq(DynamicContent::getDel, Boolean.FALSE)
        .orderByDesc(DynamicContent::getCreateTime)
        .last(getPageSql(pageNumber))
        .list();
  }

  private String getPageSql(Integer pageNumber) {

    return String.format("LIMIT %s, %s", (pageNumber - 1) * PageConstant.DEFAULT_LIMIT_SIZE,
        PageConstant.DEFAULT_LIMIT_SIZE);
  }

  @Override
  public List<DynamicContent> listByIds(Set<Long> ids) {

    if (CollectionUtils.isEmpty(ids)) {
      return Lists.newArrayList();
    }

    return Optional.ofNullable(
            query()
                .in(DynamicContent::getId, ids)
                .eq(DynamicContent::getDel, Boolean.FALSE)
                .last(PageConstant.formatLimit(ids.size())).list())
        .orElse(Lists.newArrayList());
  }

  @Override
  public Long getLatestIdByUserId(Long userId) {
    return Optional.ofNullable(
            query().select(DynamicContent::getId)
                .eq(DynamicContent::getCreateUser, userId)
                .orderByDesc(DynamicContent::getCreateTime)
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(DynamicContent::getId)
        .orElse(null);
  }

  @Override
  public DynamicContent getLatestByUserId(Long userId) {
    return query()
        .eq(DynamicContent::getCreateUser, userId)
        .orderByDesc(DynamicContent::getCreateTime)
        .getOne();
  }


  @Override
  public DynamicContent getById(Long id) {

    return query()
        .eq(DynamicContent::getId, id)
        .getOne();
  }

  @Override
  public void deleteById(Long id) {

    update()
        .set(DynamicContent::getDel, Boolean.TRUE)
        .eq(DynamicContent::getId, id)
        .last(PageConstant.LIMIT_ONE)
        .execute();

  }


  @Override
  public void deleteByIds(DelDynamicContentCmd cmd) {

    update()
        .set(DynamicContent::getDel, Boolean.TRUE)
        .set(DynamicContent::getUpdateUser, cmd.getReqUserId())
        .set(DynamicContent::getUpdateTime, TimestampUtils.now())
        .in(DynamicContent::getId, cmd.getIds())
        .last(PageConstant.formatLimit(cmd.getIds().size()))
        .execute();

  }

  @Override
  public Long getCreateUserById(Long id) {

    return Optional.ofNullable(query().select(DynamicContent::getCreateUser)
            .eq(DynamicContent::getId, id)
            .last(PageConstant.LIMIT_ONE)
            .getOne())
        .map(DynamicContent::getCreateUser)
        .orElse(null);
  }

  @Override
  public Boolean isExist(Long id) {

    return Objects.nonNull(query()
        .eq(DynamicContent::getId, id)
        .eq(DynamicContent::getDel, Boolean.FALSE)
        .last(PageConstant.LIMIT_ONE)
        .getOne());
  }


  @Override
  public PageResult<PageDynamicContentDTO> page(DynamicContentQryCmd query) {

    return MybatisConvertor.toPageResult(
        dynamicContentDAO.pageDynamic(MybatisConvertor.toPage(query.getPageQuery()), query));
  }

}
