/*
 * Original project: RedEnvelope by KaguyaStudio-MC
 * Original project link: https://github.com/KaguyaStudio-MC/RedEnvelope
 * Modified by: LeisureTimeDock
 * This file is part of RedEnvelope
 * Licensed under Camellia License Version 1.0
 */

package top.leisuretimedock.redenvelope.core.network;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import top.leisuretimedock.redenvelope.core.capability.RedEnvelopeStorage;
import top.leisuretimedock.redenvelope.core.util.REUtil;

import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;

public record RedEnvelopePacket(ItemStack itemStack, String hbtype, int count, UUID uuid, CompoundTag extraData) {

    @Contract(" -> new")
    public @NotNull RedEnvelopePacket copy() {
        return new RedEnvelopePacket(
                itemStack.copy(),
                hbtype,
                count,
                uuid,
                extraData.copy()
        );
    }

    public static void encode(@NotNull RedEnvelopePacket msg, @NotNull FriendlyByteBuf buffer) {
        buffer.writeItem(msg.itemStack);
        buffer.writeUtf(msg.hbtype);
        buffer.writeInt(msg.count);
        buffer.writeUUID(msg.uuid);
        buffer.writeNbt(msg.extraData);
    }

    public static @NotNull RedEnvelopePacket decode(@NotNull FriendlyByteBuf buffer) {
        ItemStack itemStack = buffer.readItem();
        String hbtype = buffer.readUtf();
        int count = buffer.readInt();
        UUID uuid = buffer.readUUID();
        CompoundTag extraData = buffer.readNbt();
        return new RedEnvelopePacket(itemStack, hbtype, count, uuid, extraData);
    }

    public static void handle(RedEnvelopePacket message, @NotNull Supplier<NetworkEvent.Context> ctxSupplier) {
        NetworkEvent.Context ctx = ctxSupplier.get();
        ctx.enqueueWork(() -> {
            // 判断当前是服务端还是客户端
            if (ctx.getDirection().getReceptionSide().isServer()) {
                // 服务端处理
                ServerPlayer player = ctx.getSender();
                if (player != null) {
                    handleServer(message, ctx);
                }
            } else {
                // 客户端处理
                handleClient(message, ctx);
            }
        });
        ctx.setPacketHandled(true);
    }


    // ===== 服务端处理器 =====
    public static void handleServer(RedEnvelopePacket message, NetworkEvent.@NotNull Context context) {
        context.enqueueWork(() -> {
            ServerPlayer player = context.getSender();
            if (player != null) {
                _handleServer(message, player);
            }
        });
        context.setPacketHandled(true);
    }

    public static void _handleServer(RedEnvelopePacket message, @NotNull ServerPlayer player) {
        MinecraftServer server = player.getServer();
        if (server == null) return;

        List<ServerPlayer> players = server.getPlayerList().getPlayers();

        // 给所有在线玩家添加红包数据
        players.forEach(serverPlayer -> RedEnvelopeStorage.add(serverPlayer, message.copy()));

        // 发送消息提示
        players.forEach(serverPlayer -> REUtil.receiveMessage(serverPlayer, message.copy()));

        // 如果是专用服务器，广播给所有玩家
        if (server.isDedicatedServer()) {
            RENetworkHandler.sendToAllPlayer(message);
        }
    }

    public static CompoundTag serialize(RedEnvelopePacket packet) {
        CompoundTag tag = new CompoundTag();
        tag.put("itemStack", packet.itemStack.save(new CompoundTag()));
        tag.putString("hbtype", packet.hbtype);
        tag.putInt("count", packet.count);
        tag.putUUID("uuid", packet.uuid);
        tag.put("extraData", packet.extraData);
        return tag;
    }

    public static RedEnvelopePacket deserialize(CompoundTag tag) {
        ItemStack itemStack = ItemStack.of(tag.getCompound("itemStack"));
        String hbtype = tag.getString("hbtype");
        int count = tag.getInt("count");
        UUID uuid = tag.getUUID("uuid");
        CompoundTag extraData = tag.getCompound("extraData");
        return new RedEnvelopePacket(itemStack, hbtype, count, uuid, extraData);
    }

    // ===== 客户端处理器 =====
    @OnlyIn(Dist.CLIENT)
    public static void handleClient(RedEnvelopePacket message, @NotNull NetworkEvent.Context context) {
        context.enqueueWork(() -> {
            net.minecraft.client.Minecraft mc = net.minecraft.client.Minecraft.getInstance();
            if (mc.player != null) {
                RedEnvelopeStorage.add(mc.player, message.copy());
            }
        });
        context.setPacketHandled(true);
    }
}