/*
 * Copyright (c) 2026 盐灯水母
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package com.remains_cave.block.entity;

import com.remains_cave.block.ChallengeAltarBlock;
import com.remains_cave.block.ModBlocks;
import com.remains_cave.dungeon.tomb.ChallengeType;
import com.remains_cave.dungeon.tomb.RewardConfigLoader;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.joml.Vector3f;
import com.remains_cave.dungeon.room.RoomManager;

import java.util.List;

public class ChallengeAltarBlockEntity extends BlockEntity {
    private String roomId = "";
    private ChallengeType presetType = ChallengeType.NONE;

    private boolean challengeActive = false;
    private ChallengeType activeChallengeType = ChallengeType.NONE;

    // 冷却
    public long cooldownEndTick = 0;

    // 奖励序列状态
    private boolean rewardSequenceActive = false;
    private List<ItemStack> pendingRewards;
    private int currentRewardIndex = 0;
    private int sequenceStep = 0; // 0=等待开始, 1=等待喷物品, 2=等待经验, 3=完成
    private int expRemaining = 0;

    // 计时
    private int sequenceTimer = 0;

    private int checkCooldown = 0;
    private int particleCooldown = 0;
    private static final int PLAYER_CHECK_INTERVAL_TICKS = 10;
    private static final int DUST_PARTICLE_INTERVAL_TICKS = 5;
    private static final int FLAME_PARTICLE_INTERVAL_TICKS = 5;

    private BlockPos activeAltarPos = null;

    public ChallengeAltarBlockEntity(BlockPos pos, BlockState state) {
        super(ModBlocks.CHALLENGE_ALTAR_BE.get(), pos, state);
    }

    // Getters/Setters (省略，保留原有)
    public BlockPos getActiveAltarPos() { return activeAltarPos; }
    public void setActiveAltarPos(BlockPos pos) { this.activeAltarPos = pos; setChanged(); }
    public String getRoomId() { return roomId; }
    public void setRoomId(String roomId) { this.roomId = roomId; }
    public ChallengeType getPresetType() { return presetType; }
    public void setPresetType(ChallengeType presetType) { this.presetType = presetType; setChanged(); }
    public boolean isChallengeActive() { return challengeActive; }
    public ChallengeType getActiveChallengeType() { return activeChallengeType; }
    public boolean isOnCooldown() {
        return level != null && level.getGameTime() < cooldownEndTick;
    }
    public void setCooldown(long durationTicks) {
        if (level != null) {
            this.cooldownEndTick = level.getGameTime() + durationTicks;
            setChanged();
        }
    }

    public void setChallengeActive(boolean active, ChallengeType type, BlockPos activePos) {
        this.challengeActive = active;
        this.activeChallengeType = active ? type : ChallengeType.NONE;
        this.activeAltarPos = active ? activePos : null;
        setChanged();

        if (level != null && !level.isClientSide) {
            BlockState oldState = level.getBlockState(worldPosition);
            BlockState newState = oldState.setValue(ChallengeAltarBlock.ACTIVE, active);
            level.sendBlockUpdated(worldPosition, oldState, newState, Block.UPDATE_ALL);
            var chunk = level.getChunkAt(worldPosition);
            chunk.setUnsaved(true);
            chunk.setBlockEntity(this);
            ServerLevel serverLevel = (ServerLevel) level;
            serverLevel.getChunkSource().chunkMap.getPlayers(chunk.getPos(), false)
                    .forEach(player -> player.connection.send(
                            net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket.create(this)
                    ));
            level.updateNeighborsAt(worldPosition, newState.getBlock());
        }
    }

    // 开始奖励序列
    public void startRewardSequence(List<ItemStack> rewards, ChallengeType type) {
        if (rewardSequenceActive) return;
        this.pendingRewards = rewards;
        this.currentRewardIndex = 0;
        this.sequenceStep = 1; // 等待切换开放状态
        this.sequenceTimer = 0;
        this.rewardSequenceActive = true;

        // 设置 OPEN 为 true
        BlockState state = null;
        if (level != null) {
            state = level.getBlockState(worldPosition);
        }
        if (state != null && !state.getValue(ChallengeAltarBlock.OPEN)) {
            level.setBlock(worldPosition, state.setValue(ChallengeAltarBlock.OPEN, true), Block.UPDATE_ALL);
        }
        // 播放开放音效
        if (level != null) {
            level.playSound(null, worldPosition, SoundEvents.VAULT_OPEN_SHUTTER, SoundSource.BLOCKS, 1.0f, 1.0f);
        }
    }

    private void updateRewardSequence(ServerLevel level) {
        if (!rewardSequenceActive) return;

        switch (sequenceStep) {
            case 1: // 等待1秒后开始喷物品
                if (sequenceTimer >= 20) {
                    sequenceTimer = 0;
                    sequenceStep = 2;
                } else {
                    sequenceTimer++;
                }
                break;

            case 2: // 喷物品
                if (currentRewardIndex < pendingRewards.size()) {
                    if (sequenceTimer == 0) {
                        ItemStack reward = pendingRewards.get(currentRewardIndex).copy();
                        Vec3 spawnPos = Vec3.atCenterOf(worldPosition).add(0, 1.0, 0);
                        ItemEntity itemEntity = new ItemEntity(level, spawnPos.x, spawnPos.y, spawnPos.z, reward);
                        itemEntity.setDefaultPickUpDelay();
                        level.addFreshEntity(itemEntity);
                        level.playSound(null, worldPosition, SoundEvents.VAULT_EJECT_ITEM, SoundSource.BLOCKS, 1.0f, 1.0f);
                        currentRewardIndex++;
                    }
                    sequenceTimer++;
                    if (sequenceTimer >= 20) {
                        sequenceTimer = 0;
                    }
                } else {
                    // 物品喷完，进入经验阶段
                    sequenceStep = 3;
                    sequenceTimer = 0;
                    expRemaining = 1200;
                }
                break;

            case 3: // 喷经验球
                if (expRemaining > 0) {
                    if (sequenceTimer % 3 == 0) {
                        int expToGive = Math.min(100, expRemaining);
                        ExperienceOrb.award(level, Vec3.atCenterOf(worldPosition), expToGive);
                        level.playSound(null, worldPosition, SoundEvents.TRIAL_SPAWNER_EJECT_ITEM, SoundSource.BLOCKS, 1.0f, 1.0f);
                        expRemaining -= expToGive;
                    }
                    sequenceTimer++;
                } else {
                    sequenceStep = 4;
                    sequenceTimer = 0;
                }
                break;

            case 4: // 等待1秒后关闭开放状态
                if (sequenceTimer >= 20) {
                    BlockState state = level.getBlockState(worldPosition);
                    // 先关闭 ACTIVE（如果开启），避免闪烁
                    if (state.getValue(ChallengeAltarBlock.ACTIVE)) {
                        level.setBlock(worldPosition, state.setValue(ChallengeAltarBlock.ACTIVE, false), Block.UPDATE_ALL);
                    }
                    // 再关闭 OPEN
                    if (state.getValue(ChallengeAltarBlock.OPEN)) {
                        level.setBlock(worldPosition, state.setValue(ChallengeAltarBlock.OPEN, false), Block.UPDATE_ALL);
                    }
                    level.playSound(null, worldPosition, SoundEvents.VAULT_CLOSE_SHUTTER, SoundSource.BLOCKS, 1.0f, 1.0f);
                    rewardSequenceActive = false;
                    pendingRewards = null;
                } else {
                    sequenceTimer++;
                }
                break;
        }
    }

    // 服务端 tick
    public static void serverTick(Level level, BlockPos pos, BlockState state, ChallengeAltarBlockEntity altar) {
        if (level.isClientSide) return;

        // 奖励序列优先
        if (altar.rewardSequenceActive) {
            altar.updateRewardSequence((ServerLevel) level);
            return;
        }

        // 递减冷却
        if (altar.checkCooldown > 0) altar.checkCooldown--;
        if (altar.particleCooldown > 0) altar.particleCooldown--;

        // 1. 如果挑战已激活，则跳过所有玩家交互，只保留粉尘粒子
        if (altar.challengeActive) {
            boolean isActivated = altar.activeAltarPos != null && altar.activeAltarPos.equals(pos);
            boolean targetActive = isActivated;
            if (state.getValue(ChallengeAltarBlock.ACTIVE) != targetActive) {
                level.setBlock(pos, state.setValue(ChallengeAltarBlock.ACTIVE, targetActive), Block.UPDATE_ALL);
            }
            if (altar.particleCooldown <= 0) {
                altar.addDustParticles((ServerLevel) level);
                altar.particleCooldown = DUST_PARTICLE_INTERVAL_TICKS;
            }
            if (isActivated && level.getGameTime() % 5 == 0) {
                double x = pos.getX() + 0.5;
                double y = pos.getY() + 1.2;
                double z = pos.getZ() + 0.5;
                ((ServerLevel) level).sendParticles(ParticleTypes.RAID_OMEN, x, y, z, 1, 0.2, 0.2, 0.2, 0);
            }
            return;
        }

        // 2. 冷却状态：不允许任何交互，强制关闭发光
        if (altar.isOnCooldown()) {
            if (state.getValue(ChallengeAltarBlock.ACTIVE)) {
                level.setBlock(pos, state.setValue(ChallengeAltarBlock.ACTIVE, false), Block.UPDATE_ALL);
            }
            return;
        }

        // 3. 正常逻辑（无挑战、无冷却）
        if (altar.checkCooldown <= 0) {
            altar.checkCooldown = PLAYER_CHECK_INTERVAL_TICKS;

            // 获取同一房间的所有祭坛
            String roomId = altar.getRoomId();
            boolean anyPlayerNear = false;

            if (!roomId.isEmpty()) {
                RoomManager roomManager = RoomManager.get(level);
                List<BlockPos> altars = roomManager.getAltars(roomId);
                if (altars != null) {
                    for (BlockPos altarPos : altars) {
                        if (altar.checkPlayerNearby((ServerLevel) level, altarPos)) {
                            anyPlayerNear = true;
                            break;
                        }
                    }
                }
            } else {
                // 回退：如果房间ID未设置，只检查当前祭坛
                anyPlayerNear = altar.checkPlayerNearby((ServerLevel) level, pos);
            }

            boolean currentActive = state.getValue(ChallengeAltarBlock.ACTIVE);
            if (anyPlayerNear != currentActive) {
                level.setBlock(pos, state.setValue(ChallengeAltarBlock.ACTIVE, anyPlayerNear), Block.UPDATE_ALL);
                if (anyPlayerNear) {
                    level.playSound(null, pos, SoundEvents.VAULT_ACTIVATE, SoundSource.BLOCKS, 1.0f, 1.0f);
                    for (int i = 0; i < 12; i++) {
                        double x = pos.getX() + 0.5 + (level.random.nextDouble() - 0.5) * 0.8;
                        double y = pos.getY() + 0.5 + level.random.nextDouble() * 0.8;
                        double z = pos.getZ() + 0.5 + (level.random.nextDouble() - 0.5) * 0.8;
                        ((ServerLevel) level).sendParticles(ParticleTypes.FLAME, x, y, z, 1, 0, 0.05, 0, 0);
                    }
                } else {
                    level.playSound(null, pos, SoundEvents.VAULT_DEACTIVATE, SoundSource.BLOCKS, 1.0f, 1.0f);
                }
            }
        }

        // 粉尘粒子
        if (altar.particleCooldown <= 0) {
            altar.addDustParticles((ServerLevel) level);
            altar.particleCooldown = DUST_PARTICLE_INTERVAL_TICKS;
        }

        // 火焰粒子
        BlockState finalState = level.getBlockState(pos);
        if (finalState.getValue(ChallengeAltarBlock.ACTIVE) && level.getGameTime() % FLAME_PARTICLE_INTERVAL_TICKS == 0) {
            altar.addFlameParticles((ServerLevel) level);
        }
    }

    // 其他辅助方法保持不变 (checkPlayerNearby, addDustParticles, addFlameParticles)
    private boolean checkPlayerNearby(ServerLevel level, BlockPos pos) {
        AABB aabb = new AABB(pos).inflate(4.0);
        return level.getEntitiesOfClass(Player.class, aabb)
                .stream()
                .anyMatch(p -> p.distanceToSqr(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) <= 16.0);
    }

    private void addDustParticles(ServerLevel level) {
        Vector3f redColor = new Vector3f(0.898f, 0.314f, 0.314f);
        for (int i = 0; i < 2; i++) {
            double x = worldPosition.getX() + 0.5 + (level.random.nextDouble() - 0.5);
            double y = worldPosition.getY() + 0.2 + level.random.nextDouble() * 0.8;
            double z = worldPosition.getZ() + 0.5 + (level.random.nextDouble() - 0.5);
            double vx = (level.random.nextDouble() - 0.5) * 0.05;
            double vy = level.random.nextDouble() * 0.1;
            double vz = (level.random.nextDouble() - 0.5) * 0.05;
            level.sendParticles(new DustParticleOptions(redColor, 0.8f), x, y, z, 1, vx, vy, vz, 0);
        }
    }

    private void addFlameParticles(ServerLevel level) {
        for (int i = 0; i < 2; i++) {
            double x = worldPosition.getX() + 0.5 + (level.random.nextDouble() - 0.5) * 0.8;
            double y = worldPosition.getY() + 0.5 + level.random.nextDouble() * 0.8;
            double z = worldPosition.getZ() + 0.5 + (level.random.nextDouble() - 0.5) * 0.8;
            level.sendParticles(ParticleTypes.FLAME, x, y, z, 1, 0, 0.05, 0, 0);
        }
    }

    public static void clientTick(Level level, BlockPos pos, BlockState state, ChallengeAltarBlockEntity altar) {}

    @Override
    public @NotNull CompoundTag getUpdateTag(HolderLookup.@NotNull Provider registries) {
        CompoundTag tag = super.getUpdateTag(registries);
        tag.putString("RoomId", roomId);
        tag.putString("PresetType", presetType.getSerializedName());
        tag.putBoolean("ChallengeActive", challengeActive);
        if (challengeActive) {
            tag.putString("ActiveChallengeType", activeChallengeType.getSerializedName());
        }
        if (activeAltarPos != null) {
            tag.put("ActiveAltarPos", NbtUtils.writeBlockPos(activeAltarPos));
        }
        tag.putLong("CooldownEndTick", cooldownEndTick);
        return tag;
    }
    @Override
    public void handleUpdateTag(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
        super.handleUpdateTag(tag, registries);
        loadAdditional(tag, registries);
    }

    // 数据持久化
    @Override
    public void loadAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
        super.loadAdditional(tag, registries);
        roomId = tag.getString("RoomId");
        if (tag.contains("PresetType")) {
            String presetName = tag.getString("PresetType");
            try {
                presetType = ChallengeType.valueOf(presetName.toUpperCase());
            } catch (IllegalArgumentException e) {
                presetType = ChallengeType.NONE;
            }
        }
        if (tag.contains("ActiveAltarPos")) {
            activeAltarPos = NbtUtils.readBlockPos(tag, "ActiveAltarPos").orElse(null);
        } else {
            activeAltarPos = null;
        }
        challengeActive = tag.getBoolean("ChallengeActive");
        if (challengeActive && tag.contains("ActiveChallengeType")) {
            String typeName = tag.getString("ActiveChallengeType");
            try {
                activeChallengeType = ChallengeType.valueOf(typeName.toUpperCase());
            } catch (IllegalArgumentException e) {
                activeChallengeType = ChallengeType.NONE;
                challengeActive = false;
            }
        } else {
            activeChallengeType = ChallengeType.NONE;
        }
        cooldownEndTick = tag.getLong("CooldownEndTick");
        // 奖励序列状态不持久化（如果重启时正在序列，丢弃）
    }

    @Override
    protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
        super.saveAdditional(tag, registries);
        tag.putString("RoomId", roomId);
        tag.putString("PresetType", presetType.getSerializedName());
        tag.putBoolean("ChallengeActive", challengeActive);
        if (challengeActive) {
            tag.putString("ActiveChallengeType", activeChallengeType.getSerializedName());
        }
        if (activeAltarPos != null) {
            tag.put("ActiveAltarPos", NbtUtils.writeBlockPos(activeAltarPos));
        }
        tag.putLong("CooldownEndTick", cooldownEndTick);
    }

}