package com.red.circle.other.app.inner.endpoint.activity;

import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryActivity;
import com.red.circle.other.infra.database.rds.service.activity.LotteryActivityService;
import com.red.circle.other.inner.asserts.lottery.LotteryErrorCode;
import com.red.circle.other.inner.endpoint.activity.api.LotteryActivityManageClientApi;
import com.red.circle.other.inner.model.cmd.activity.LotteryActivitySaveCmd;
import com.red.circle.other.inner.model.dto.activity.LotteryActivityDTO;
import java.sql.Timestamp;

import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 抽奖活动管理ClientEndpoint.
 *
 * @author system
 * @since 2025-10-18
 */
@Validated
@RestController
@RequestMapping(value = LotteryActivityManageClientApi.API_PREFIX, produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class LotteryActivityManageClientEndpoint implements LotteryActivityManageClientApi {

  private final LotteryActivityService lotteryActivityService;

  @Override
  @Transactional(rollbackFor = Exception.class)
  public ResultResponse<Void> createActivity(LotteryActivitySaveCmd cmd) {
    // 校验活动编码唯一性
    LotteryActivity exists = lotteryActivityService.query()
        .eq(LotteryActivity::getActivityCode, cmd.getActivityCode())
        .getOne();
    ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_CODE_EXISTS, exists == null);

    LotteryActivity activity = new LotteryActivity();
    BeanUtils.copyProperties(cmd, activity);
    activity.setStatus(0); // 未开始
    activity.setTotalStock(0);
    activity.setConsumedStock(0);
    
    lotteryActivityService.save(activity);
    
    return ResultResponse.success();
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public ResultResponse<Void> updateActivity(LotteryActivitySaveCmd cmd) {
    ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_ID_REQUIRED, cmd.getId() != null);

    LotteryActivity activity = lotteryActivityService.getById(cmd.getId());
    ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_NOT_FOUND, activity != null);

    BeanUtils.copyProperties(cmd, activity);
    lotteryActivityService.updateSelectiveById(activity);
    
    return ResultResponse.success();
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public ResultResponse<Void> updateActivityStatus(Long id, Integer status) {
    LotteryActivity activity = lotteryActivityService.getById(id);
    ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_NOT_FOUND, activity != null);

    Integer currentStatus = activity.getStatus();
    Timestamp now = TimestampUtils.now();

    // 状态校验规则：0-未开始，1-进行中，2-已结束，3-已关闭
    // 1. 未开始(0) -> 可以转换为：进行中(1)、已关闭(3)
    // 2. 进行中(1) -> 可以转换为：已结束(2)、已关闭(3)
    // 3. 已结束(2) -> 可以转换为：已关闭(3)
    // 4. 已关闭(3) -> 不可再转换

    // 校验：已关闭的活动不能再修改状态
    ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_STATUS_NOT_ALLOW_UPDATE, 
        currentStatus != 3);

    // 校验状态转换的合法性
    if (currentStatus == 0) {
      // 未开始 -> 只能转换为 进行中(1) 或 已关闭(3)
      ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_STATUS_NOT_ALLOW_UPDATE,
          status == 1 || status == 3);
      
      // 转换为进行中时，需要校验时间
      if (status == 1) {
        ResponseAssert.isTrue(LotteryErrorCode.NOT_IN_ACTIVITY_TIME,
            now.after(activity.getStartTime()) || now.equals(activity.getStartTime()));
        ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_ENDED,
            now.before(activity.getEndTime()));
      }
    } else if (currentStatus == 1) {
      // 进行中 -> 只能转换为 已结束(2) 或 已关闭(3)
      ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_STATUS_NOT_ALLOW_UPDATE,
          status == 2 || status == 3);
    } else if (currentStatus == 2) {
      // 已结束 -> 只能转换为 已关闭(3)
      ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_STATUS_NOT_ALLOW_UPDATE,
          status == 3);
    }

    activity.setStatus(status);
    lotteryActivityService.updateSelectiveById(activity);
    
    return ResultResponse.success();
  }

  @Override
  public ResultResponse<LotteryActivityDTO> getById(Long id) {
    LotteryActivity activity = lotteryActivityService.getById(id);
    ResponseAssert.isTrue(LotteryErrorCode.ACTIVITY_NOT_FOUND, activity != null);
    
    LotteryActivityDTO dto = new LotteryActivityDTO();
    BeanUtils.copyProperties(activity, dto);
    
    return ResultResponse.success(dto);
  }

}
