package com.red.circle.order.infra.database.mongo.order.impl;

import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseCollectionReceiptService;
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseCollectionReceipt;
import com.red.circle.order.infra.database.mongo.order.query.InAppPurchaseCollectionReceiptQuery;
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseCollectionReceiptStatus;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

/**
 * @author pengliang on 2022/10/26
 */
@Service
@RequiredArgsConstructor
public class InAppPurchaseCollectionReceiptServiceImpl implements
    InAppPurchaseCollectionReceiptService {

  private static final String ID_FIELD = "_id";

  private final MongoTemplate mongoTemplate;

  @Override
  public void create(InAppPurchaseCollectionReceipt receipt) {
    mongoTemplate.save(receipt);
  }

  @Override
  public void update(InAppPurchaseCollectionReceipt receipt) {
    mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(receipt.getId())),
        new Update()
            .set("acceptUserId", receipt.getAcceptUserId())
            .set("amount", receipt.getAmount())
            .set("amountUsd", receipt.getAmountUsd())
            .set("usdExchangeRate", receipt.getUsdExchangeRate())
            .set("currency", receipt.getCurrency())
            .set("title", receipt.getTitle())
            .set("describe", receipt.getDescribe())
            .set("products", receipt.getProducts())
            .set("customChannels", receipt.getCustomChannels())
            .set("updateTime", TimestampUtils.now())
            .set("updateUser", receipt.getUpdateUser()),
        InAppPurchaseCollectionReceipt.class);
  }

  @Override
  public void close(String id, Long operationUserId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
        new Update()
            .set("updateTime", TimestampUtils.now())
            .set("status", InAppPurchaseCollectionReceiptStatus.CLOSE)
            .set("updateUser", operationUserId),
        InAppPurchaseCollectionReceipt.class);
  }

  @Override
  public void updateStatusSuccess(String id) {
    mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
        new Update()
            .set("updateTime", TimestampUtils.now())
            .set("status", InAppPurchaseCollectionReceiptStatus.SUCCESS)
            .set("lockTime", TimestampUtils.now()),
        InAppPurchaseCollectionReceipt.class);
  }

  @Override
  public void updateStatusSuccessFail(String id) {
    mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
        new Update()
            .set("updateTime", TimestampUtils.now())
            .set("status", InAppPurchaseCollectionReceiptStatus.FAIL)
            .set("lockTime", TimestampUtils.now()),
        InAppPurchaseCollectionReceipt.class);
  }

  @Override
  public List<InAppPurchaseCollectionReceipt> list(
      InAppPurchaseCollectionReceiptQuery query) {

    Criteria criteria = StringUtils.isBlank(query.getSysOrigin())
        ? new Criteria()
        : Criteria.where("sysOrigin").is(query.getSysOrigin());

    if (StringUtils.isNotBlank(query.getId())) {
      query.setLastId(null);
      criteria.and(ID_FIELD).is(query.getId());
    }

    if (StringUtils.isNotBlank(query.getStatus())) {
      criteria.and("status").is(query.getStatus());
    }

    if (Objects.nonNull(query.getAcceptUserId())) {
      criteria.and("acceptUserId").is(query.getAcceptUserId());
    }

    if (Objects.nonNull(query.getCreateUserId())) {
      criteria.and("createUser").is(query.getCreateUserId());
    }

    if (Objects.nonNull(query.getStartTime()) && Objects.nonNull(query.getEndTime())) {
      criteria.andOperator(
          Criteria.where("createTime").gte(query.getStartTime()),
          Criteria.where("createTime").lte(query.getEndTime())
      );
    }

    if (Objects.nonNull(query.getLastId())) {
      criteria.and(ID_FIELD).lt(query.getLastId());
    }

    if (Objects.isNull(query.getLimit())) {
      query.setLimit(PageConstant.DEFAULT_LIMIT_SIZE);
    }

    return mongoTemplate.find(Query.query(criteria)
            .with(Sort.by(Sort.Order.desc(ID_FIELD)))
            .limit(query.getLimit()),
        InAppPurchaseCollectionReceipt.class);
  }

  @Override
  public InAppPurchaseCollectionReceipt getById(String id) {
    return mongoTemplate.findOne(Query.query(Criteria.where(ID_FIELD).is(id)),
        InAppPurchaseCollectionReceipt.class);
  }

  @Override
  public void lockTime(String id, long minute) {
    mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
        new Update()
            .set("updateTime", TimestampUtils.now())
            .set("lockTime", TimestampUtils.nowPlusMinutes(minute)),
        InAppPurchaseCollectionReceipt.class);
  }

}
