package com.red.circle.console.app.service.app.activity;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.red.circle.console.app.dto.clienobject.app.activity.register.ResidentRegisterRewardConfigCO;
import com.red.circle.console.app.dto.cmd.app.activity.register.ResidentRegisterRewardConfigSaveCmd;
import com.red.circle.console.app.service.app.props.PropsActivityRewardGroupService;
import com.red.circle.console.infra.database.rds.entity.app.register.ResidentRegisterRewardConfig;
import com.red.circle.console.infra.database.rds.service.app.register.ResidentRegisterRewardConfigService;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.core.response.ResponseErrorCode;
import com.red.circle.other.inner.model.dto.material.PropsActivityRewardGroupDTO;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 常驻注册奖励服务实现.
 */
@Service
@RequiredArgsConstructor
public class ResidentRegisterRewardServiceImpl implements ResidentRegisterRewardService {

  private final ResidentRegisterRewardConfigService residentRegisterRewardConfigService;
  private final PropsActivityRewardGroupService propsActivityRewardGroupService;

  @Override
  public ResidentRegisterRewardConfigCO getConfig(String sysOrigin) {
    String normalizedSysOrigin = normalizeSysOrigin(sysOrigin);
    ResidentRegisterRewardConfig config = residentRegisterRewardConfigService.query()
        .eq(ResidentRegisterRewardConfig::getSysOrigin, normalizedSysOrigin)
        .getOne();

    ResidentRegisterRewardConfigCO result = new ResidentRegisterRewardConfigCO()
        .setSysOrigin(normalizedSysOrigin);
    if (config == null) {
      return result;
    }

    return result.setConfigured(Boolean.TRUE)
        .setEnabled(Boolean.TRUE.equals(config.getEnabled()))
        .setGoldAmount(defaultGoldAmount(config.getGoldAmount()))
        .setDailyLimit(defaultDailyLimit(config.getDailyLimit()))
        .setRewardGroupId(config.getRewardGroupId())
        .setRewardGroupName(getRewardGroupName(config.getRewardGroupId()));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void saveConfig(ResidentRegisterRewardConfigSaveCmd cmd) {
    validateConfig(cmd);
    String normalizedSysOrigin = normalizeSysOrigin(cmd.getSysOrigin());
    ResidentRegisterRewardConfig config = residentRegisterRewardConfigService.query()
        .eq(ResidentRegisterRewardConfig::getSysOrigin, normalizedSysOrigin)
        .getOne();
    boolean exists = config != null;
    if (!exists) {
      config = new ResidentRegisterRewardConfig().setId(IdWorkerUtils.getId());
    }

    config.setSysOrigin(normalizedSysOrigin)
        .setEnabled(Boolean.TRUE.equals(cmd.getEnabled()))
        .setGoldAmount(defaultGoldAmount(cmd.getGoldAmount()))
        .setDailyLimit(defaultDailyLimit(cmd.getDailyLimit()))
        .setRewardGroupId(cmd.getRewardGroupId());

    if (exists) {
      ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
          residentRegisterRewardConfigService.updateSelectiveById(config));
      return;
    }
    ResponseAssert.isTrue(CommonErrorCode.SAVE_FAILURE,
        residentRegisterRewardConfigService.save(config));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void resetConfig(String sysOrigin) {
    String normalizedSysOrigin = normalizeSysOrigin(sysOrigin);
    residentRegisterRewardConfigService.remove(
        Wrappers.<ResidentRegisterRewardConfig>lambdaQuery()
            .eq(ResidentRegisterRewardConfig::getSysOrigin, normalizedSysOrigin));
  }

  private void validateConfig(ResidentRegisterRewardConfigSaveCmd cmd) {
    long goldAmount = defaultGoldAmount(cmd.getGoldAmount());
    long dailyLimit = defaultDailyLimit(cmd.getDailyLimit());
    if (Boolean.TRUE.equals(cmd.getEnabled())) {
      ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
          "At least one reward is required when enabled.",
          goldAmount > 0 || cmd.getRewardGroupId() != null);
    }
    ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
        "goldAmount must be greater than or equal to zero.",
        goldAmount >= 0);
    ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
        "dailyLimit must be greater than or equal to zero.",
        dailyLimit >= 0);
  }

  private String normalizeSysOrigin(String sysOrigin) {
    return Objects.toString(sysOrigin, "").trim().toUpperCase();
  }

  private Long defaultGoldAmount(Long goldAmount) {
    return goldAmount == null ? 0L : goldAmount;
  }

  private Long defaultDailyLimit(Long dailyLimit) {
    return dailyLimit == null ? 0L : dailyLimit;
  }

  private String getRewardGroupName(Long rewardGroupId) {
    if (rewardGroupId == null) {
      return null;
    }
    try {
      PropsActivityRewardGroupDTO group = propsActivityRewardGroupService.getByGroupId(rewardGroupId);
      return group == null ? null : group.getName();
    } catch (Exception ignore) {
      return null;
    }
  }
}
