package com.red.circle.other.app.command.rocket;

import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.external.inner.endpoint.message.ImGroupClient;
import com.red.circle.external.inner.model.cmd.message.BroadcastGroupMsgBodyCmd;
import com.red.circle.external.inner.model.enums.message.GroupMessageTypeEnum;
import com.red.circle.live.inner.endpoint.LiveRoomUserClient;
import com.red.circle.live.inner.model.LiveMicUserDTO;
import com.red.circle.other.app.convertor.RocketConvertor;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.RocketStatusCO;
import com.red.circle.other.app.manager.RocketImPushManager;
import com.red.circle.other.app.service.room.RocketStatusCacheService;
import com.red.circle.other.app.util.DistributedLockUtil;
import com.red.circle.other.app.util.OfficialNoticeUtils;
import com.red.circle.other.domain.gateway.RocketConfigGateway;
import com.red.circle.other.domain.gateway.RocketHistoryGateway;
import com.red.circle.other.domain.gateway.RocketStatusGateway;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.rocket.RocketHistory;
import com.red.circle.other.domain.rocket.RocketLevel;
import com.red.circle.other.domain.rocket.RocketStatus;
import com.red.circle.other.domain.rocket.RocketStatusEnum;
import com.red.circle.other.infra.database.cache.key.RocketKeys;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 火箭发射命令执行器
 * 优化版：发射后自动升级到下一级火箭
 *
 * @author system
 * @date 2025-01-15
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RocketLaunchCmdExe {

    private final RocketStatusGateway rocketStatusGateway;
    private final RocketHistoryGateway rocketHistoryGateway;
    private final DistributedLockUtil distributedLockUtil;
    private final RocketImPushManager rocketImPushManager;
    private final RocketConfigGateway rocketConfigGateway;
    private final RoomProfileManagerService roomProfileManagerService;
    private final ImGroupClient imGroupClient;
    private final UserProfileGateway userProfileGateway;
    private final UserProfileAppConvertor userProfileAppConvertor;
    private final RocketRewardClaimCmdExe rocketRewardClaimCmdExe;
    private final LiveRoomUserClient liveRoomUserClient;
    private final RocketStatusCacheService rocketStatusCacheService;

    /**
     * 执行火箭发射
     * @param roomId 房间ID
     * @param triggerUserId 触发升级的用户ID
     */
    public void execute(Long roomId, Long triggerUserId) {
        String lockKey = RocketKeys.LAUNCH.getKey(roomId);
        
        distributedLockUtil.executeWithLock(lockKey, 10L, () -> {
            doLaunch(roomId, triggerUserId);
            return null;
        }, "火箭发射操作过于频繁，请稍后重试");
    }

    /**
     * 执行发射逻辑
     */
    private void doLaunch(Long roomId, Long triggerUserId) {
        // 1. 查询当前火箭状态（需要完整数据，包含贡献者）
        String today = LocalDate.now().toString();
        RocketStatus rocketStatus = rocketStatusGateway.findByRoomIdAndDate(roomId, today);
        
        if (rocketStatus == null) {
            log.warn("火箭状态不存在, roomId={}", roomId);
            return;
        }

        // 2. 校验状态
        if (rocketStatus.getStatus() != RocketStatusEnum.CHARGING) {
            log.warn("火箭状态不正确, 无法发射, roomId={}, status={}", roomId, rocketStatus.getStatus());
            return;
        }

        // 3. 校验能量
        if (!rocketStatus.isFullEnergy()) {
            log.warn("火箭能量不足, 无法发射, roomId={}, currentEnergy={}, maxEnergy={}", 
                    roomId, rocketStatus.getCurrentEnergy(), rocketStatus.getMaxEnergy());
            return;
        }

        // 4. 记录发射前的等级（用于日志和历史）
        int launchedLevel = rocketStatus.getLevel().getLevel();
        long finalEnergy = rocketStatus.getCurrentEnergy();
        int contributorCount = rocketStatus.getContributors() != null ? rocketStatus.getContributors().size() : 0;

        // 5. 发射并自动升级到下一级
        // 1. 先计算出能发射的等级
        RocketLevel launchLevel = rocketStatus.calculateLaunchLevel(rocketConfigGateway);
        if (launchLevel == null) {
            return;
        }

        // 2. 标记为已发射状态
        rocketStatus.markAsLaunched();

        // 3. 保存发射时的历史记录（此时还是发射等级）
        try {
            rocketStatus.setLevel(launchLevel);
            RocketHistory history = RocketHistory.fromRocketStatus(rocketStatus);
            String historyId = rocketHistoryGateway.save(history);
            log.info("保存火箭历史记录成功: historyId={}, roomId={}, level={}",
                    historyId, roomId, launchLevel.getLevel());
        } catch (Exception e) {
            log.error("保存火箭历史记录失败: roomId={}", roomId, e);
        }

        // 4. 找到下一个等级
        RocketLevel nextLevel = launchLevel.getNextLevel();
        // 5. 升级到下一个等级
        rocketStatus.upgradeToLevel(rocketConfigGateway, nextLevel);

        // 8. 保存新状态
        rocketStatusGateway.save(rocketStatus);

        // 9. 广播升级消息（带触发用户信息）
        try {
            broadcastRocketUpgrade(roomId, launchedLevel, rocketStatus.getLevel().getLevel(), triggerUserId);
        } catch (Exception e) {
            log.error("广播火箭升级消息失败: roomId={}", roomId, e);
        }

        // 设置新的火箭状态
        rocketStatusCacheService.batchSetRocketStatus(List.of(rocketStatus));

        String roomAccount = roomProfileManagerService.getRoomAccount(roomId);

        // 给所有在线的用户发送奖励
        try {
            List<LiveMicUserDTO> userDTOS = liveRoomUserClient.userList(roomId).getBody();
            userDTOS.forEach(userDTO -> {
                rocketRewardClaimCmdExe.executeAsync(roomId, roomAccount, userDTO.getId(), userDTO.getUserNickname());
            });
        } catch (Exception e) {
            log.error("给所有在线的用户发送奖励失败: roomId={}", roomId,  e);
        }

        log.info("火箭发射并升级成功: roomId={}, 发射等级={}, 最终能量={}, 贡献者数={}, 升级到={}, 触发用户={}", 
                roomId, 
                launchedLevel,
                finalEnergy,
                contributorCount,
                rocketStatus.getLevel().getLevel(),
                triggerUserId);

        // 10. 推送升级后的状态消息
        try {
            RocketStatusCO newStatusCO = RocketConvertor.toStatusCO(rocketStatus);
            rocketImPushManager.pushEnergyUpdate(roomAccount, newStatusCO);
        } catch (Exception e) {
            log.error("推送火箭升级消息失败: roomId={}", roomId, e);
        }
    }

    /**
     * 广播火箭升级消息
     */
    private void broadcastRocketUpgrade(Long roomId, int fromLevel, int toLevel, Long triggerUserId) {
        try {

            UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
                    userProfileGateway.getByUserId(triggerUserId));
            Map<Object, Object> build = OfficialNoticeUtils.buildUserProfile(userProfile);
            build.put("roomId", roomId);
            build.put("fromLevel", fromLevel);
//            build.put("toLevel", toLevel);
            imGroupClient.sendMessageBroadcast(
                    BroadcastGroupMsgBodyCmd.builder()
                            .toPlatform(SysOriginPlatformEnum.LIKEI)
                            .type(GroupMessageTypeEnum.ROCKET_ENERGY_LAUNCH)
                            .data(build)
                            .build()
            );
        } catch (Exception e) {
            log.error("广播火箭升级消息失败: roomId={}, triggerUserId={}", roomId, triggerUserId, e);
            throw e;
        }
    }
}
