package com.tiedup.remake.network.cell;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.network.base.AbstractClientPacket;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 * Packet to open the CellManager screen on the client.
 * Sends list of cells accessible to the player.
 *
 * For operators: sends ALL cells with ability to manage any
 * For non-operators: sends only owned cells
 *
 * Server -> Client
 */
public class PacketOpenCellManager extends AbstractClientPacket {

    private final List<CellSyncData> cells;
    private final boolean isOperator;

    /**
     * Network-serializable cell data.
     */
    public static class CellSyncData {

        public final UUID cellId;
        public final String name;
        public final BlockPos spawnPoint;
        public final int prisonerCount;
        public final int maxPrisoners;
        public final List<PrisonerInfo> prisoners;
        public final boolean isOwned; // true if the viewing player owns this cell
        public final String ownerName; // Owner's name (for OPs viewing other players' cells)

        public CellSyncData(
            UUID cellId,
            String name,
            BlockPos spawnPoint,
            int prisonerCount,
            int maxPrisoners,
            List<PrisonerInfo> prisoners,
            boolean isOwned,
            String ownerName
        ) {
            this.cellId = cellId;
            this.name = name;
            this.spawnPoint = spawnPoint;
            this.prisonerCount = prisonerCount;
            this.maxPrisoners = maxPrisoners;
            this.prisoners = prisoners != null ? prisoners : new ArrayList<>();
            this.isOwned = isOwned;
            this.ownerName = ownerName;
        }

        /**
         * Legacy constructor for backward compatibility.
         */
        public CellSyncData(
            UUID cellId,
            String name,
            BlockPos spawnPoint,
            int prisonerCount,
            int maxPrisoners,
            List<PrisonerInfo> prisoners
        ) {
            this(
                cellId,
                name,
                spawnPoint,
                prisonerCount,
                maxPrisoners,
                prisoners,
                true,
                null
            );
        }

        /**
         * Get display name (name or truncated UUID).
         */
        public String getDisplayName() {
            if (name != null && !name.isEmpty()) {
                return name;
            }
            return "Cell " + cellId.toString().substring(0, 8);
        }
    }

    /**
     * Network-serializable prisoner info.
     */
    public static class PrisonerInfo {

        public final UUID prisonerId;
        public final String prisonerName;

        public PrisonerInfo(UUID prisonerId, String prisonerName) {
            this.prisonerId = prisonerId;
            this.prisonerName = prisonerName;
        }
    }

    public PacketOpenCellManager(List<CellSyncData> cells, boolean isOperator) {
        this.cells = cells != null ? cells : new ArrayList<>();
        this.isOperator = isOperator;
    }

    /**
     * Legacy constructor for backward compatibility (assumes not operator).
     */
    public PacketOpenCellManager(List<CellSyncData> cells) {
        this(cells, false);
    }

    public void encode(FriendlyByteBuf buf) {
        buf.writeBoolean(this.isOperator);
        buf.writeInt(this.cells.size());

        for (CellSyncData cell : this.cells) {
            buf.writeUUID(cell.cellId);
            buf.writeBoolean(cell.name != null);
            if (cell.name != null) {
                buf.writeUtf(cell.name, 64);
            }
            buf.writeBlockPos(cell.spawnPoint);
            buf.writeInt(cell.prisonerCount);
            buf.writeInt(cell.maxPrisoners);
            buf.writeBoolean(cell.isOwned);
            buf.writeBoolean(cell.ownerName != null);
            if (cell.ownerName != null) {
                buf.writeUtf(cell.ownerName, 64);
            }

            // Write prisoners
            buf.writeInt(cell.prisoners.size());
            for (PrisonerInfo prisoner : cell.prisoners) {
                buf.writeUUID(prisoner.prisonerId);
                buf.writeUtf(prisoner.prisonerName, 64);
            }
        }
    }

    public static PacketOpenCellManager decode(FriendlyByteBuf buf) {
        boolean isOperator = buf.readBoolean();
        int cellCount = buf.readInt();
        List<CellSyncData> cells = new ArrayList<>();

        for (int i = 0; i < cellCount; i++) {
            UUID cellId = buf.readUUID();
            String name = buf.readBoolean() ? buf.readUtf(64) : null;
            BlockPos spawnPoint = buf.readBlockPos();
            int prisonerCount = buf.readInt();
            int maxPrisoners = buf.readInt();
            boolean isOwned = buf.readBoolean();
            String ownerName = buf.readBoolean() ? buf.readUtf(64) : null;

            // Read prisoners
            int prisonerListSize = buf.readInt();
            List<PrisonerInfo> prisoners = new ArrayList<>();
            for (int j = 0; j < prisonerListSize; j++) {
                UUID prisonerId = buf.readUUID();
                String prisonerName = buf.readUtf(64);
                prisoners.add(new PrisonerInfo(prisonerId, prisonerName));
            }

            cells.add(
                new CellSyncData(
                    cellId,
                    name,
                    spawnPoint,
                    prisonerCount,
                    maxPrisoners,
                    prisoners,
                    isOwned,
                    ownerName
                )
            );
        }

        return new PacketOpenCellManager(cells, isOperator);
    }

    @Override
    @OnlyIn(Dist.CLIENT)
    protected void handleClientImpl() {
        ClientHandler.handle(this);
    }

    @OnlyIn(Dist.CLIENT)
    private static class ClientHandler {

        private static void handle(PacketOpenCellManager pkt) {
            net.minecraft.client.Minecraft mc =
                net.minecraft.client.Minecraft.getInstance();
            if (mc.player == null) return;

            TiedUpMod.LOGGER.info(
                "[PacketOpenCellManager] Opening cell manager with {} cells (operator: {})",
                pkt.cells.size(),
                pkt.isOperator
            );

            mc.setScreen(
                new com.tiedup.remake.client.gui.screens.CellManagerScreen(
                    pkt.cells,
                    pkt.isOperator
                )
            );
        }
    }

    public List<CellSyncData> getCells() {
        return cells;
    }

    public boolean isOperator() {
        return isOperator;
    }
}
