package com.red.circle.other.app.command.activity.room;

import com.red.circle.component.redis.service.RedisService;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.dto.cmd.activity.room.ReceiveRoomRewardCmd;
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
import com.red.circle.other.infra.database.mongo.service.activity.RoomContributionActivityCountService;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.inner.asserts.ActivityErrorCode;
import com.red.circle.other.inner.asserts.RoomErrorCode;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * 领取房间奖励房主收入执行器
 *
 * @author system
 * @date 2025-12-01
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ReceiveRoomRewardCmdExe {

    private final WalletGoldClient walletGoldClient;
    private final RoomProfileManagerService roomProfileManagerService;
    private final RoomContributionActivityCountService roomContributionActivityCountService;
    private final MongoTemplate mongoTemplate;

    @Transactional(rollbackFor = Exception.class)
    public void execute(ReceiveRoomRewardCmd cmd) {
        Long userId = cmd.getReqUserId();
        String roomId = cmd.getRoomId();

        // 2. 校验用户是否是房主
        Long userRoomId = roomProfileManagerService.getRoomId(userId);
        ResponseAssert.isTrue(
                RoomErrorCode.NOT_ROOM_OWNER,
                Objects.equals(userRoomId, Long.parseLong(roomId))
        );

        // 3. 查询上周数据
        String lastWeekDateNumber = ZonedDateTimeAsiaRiyadhUtils.getLastWeekMonday().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        RoomContributionActivityCount lastWeekData = roomContributionActivityCountService
                .findByRoomIdAndDateNumber(Long.parseLong(roomId), Integer.valueOf(lastWeekDateNumber))
                .orElse(null);

        ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, lastWeekData);

        // 4. 校验是否已领取
        ResponseAssert.isFalse(ActivityErrorCode.AWARD_RECEIVED,
                Optional.ofNullable(lastWeekData.getReceived()).orElse(false));

        // 5. 计算房主收入（流水 * ratio）
        BigDecimal contributionValue = lastWeekData.getContributionValue();
        ResponseAssert.notNull(CommonErrorCode.DATA_ERROR, contributionValue);
        
        BigDecimal ratio = Optional.ofNullable(lastWeekData.getRatio()).orElse(new BigDecimal("0.05"));
        
        BigDecimal ownerIncome = contributionValue.multiply(ratio).setScale(0, RoundingMode.DOWN);
        
        ResponseAssert.isTrue(
                CommonErrorCode.DATA_ERROR,
                ownerIncome.compareTo(BigDecimal.ZERO) > 0
        );

        // 6. 调用钱包服务增加金币
        walletGoldClient.changeBalance(GoldReceiptCmd.builder()
                .appIncome()
                .eventId(Long.parseLong(roomId))
                .userId(userId)
                .sysOrigin(cmd.getReqSysOrigin().getOrigin())
                .origin(GoldOrigin.ROOM_CONTRIBUTION_REWARD)
                .amount(ownerIncome)
                .build());

        // 7. 更新received状态为true
        Query query = new Query(Criteria.where("_id").is(lastWeekData.getId()));
        Update update = new Update().set("received", true);
        mongoTemplate.updateFirst(query, update, RoomContributionActivityCount.class);

        log.info("房间奖励领取成功, userId={}, roomId={}, dateNumber={}, income={}",
                userId, roomId, lastWeekDateNumber, ownerIncome);
    }

}
