package com.red.circle.wallet.infra.database.rds.service.impl;

import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.tool.core.date.DateUtils;
import com.red.circle.wallet.infra.database.rds.dao.WalletGoldBalanceDAO;
import com.red.circle.wallet.infra.database.rds.entity.WalletGoldBalance;
import com.red.circle.wallet.infra.database.rds.service.WalletGoldBalanceService;
import java.util.Objects;
import java.util.Optional;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

/**
 * 用户金币钱包 服务类实现.
 *
 * @author pengliang on 2023/6/30
 */
@Service
public class WalletGoldBalanceServiceImpl extends
    BaseServiceImpl<WalletGoldBalanceDAO, WalletGoldBalance> implements WalletGoldBalanceService {

  @Override
  public boolean exists(Long userId) {
    return Optional.ofNullable(query()
            .select(WalletGoldBalance::getId)
            .eq(WalletGoldBalance::getId, userId)
            .last(PageConstant.LIMIT_ONE)
            .getOne())
        .map(obj -> Objects.nonNull(obj.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public void init(String sysOrigin, Long userId, Long income, Long expenditure) {
    try {
      save(new WalletGoldBalance()
          .setId(userId)
          .setSysOrigin(sysOrigin)
          .setIncome(income)
          .setExpenditure(expenditure)
      );
    } catch (DuplicateKeyException ex) {
      // ignore
    }
  }

  public Long getBalance(Long userId) {
    Long balance = Optional.ofNullable(getById(userId))
        .map(wallet -> wallet.getIncome() - wallet.getExpenditure())
        .orElse(0L);
    return balance > 0 ? balance : 0L;
  }
  @Override
  public Long getBalanceTotal(Long userId) {
    Long balance = Optional.ofNullable(getById(userId))
        .map(WalletGoldBalance::getIncome)
        .orElse(0L);
    return balance > 0 ? balance : 0L;
  }


  @Override
  public void incrIncome(Long userId, Long amount) {
    update().set(WalletGoldBalance::getUpdateTime, DateUtils.now())
        .setSql(String.format("income=income+%s", amount))
        .eq(WalletGoldBalance::getId, userId)
        .last(PageConstant.LIMIT_ONE)
        .execute();
  }

  @Override
  public void incrExpenditure(Long userId, Long amount) {
    update().set(WalletGoldBalance::getUpdateTime, DateUtils.now())
        .setSql(String.format("expenditure=expenditure+%s", amount))
        .eq(WalletGoldBalance::getId, userId)
        .last(PageConstant.LIMIT_ONE)
        .execute();
  }

  @Override
  public boolean incrExpenditureCas(Long userId, Long amount, Long amountCas) {
    return update().set(WalletGoldBalance::getUpdateTime, DateUtils.now())
        .setSql(String.format("expenditure=expenditure+%s", amount))
        .eq(WalletGoldBalance::getId, userId)
        .eq(WalletGoldBalance::getExpenditure, amountCas)
        .last(PageConstant.LIMIT_ONE)
        .execute();
  }

  @Override
  public boolean clear(Long userId) {
    return update()
        .setSql("expenditure=income")
        .eq(WalletGoldBalance::getId, userId)
        .execute();
  }

}
