package de.winniepat.citrus.gui;

import de.winniepat.citrus.cosmetics.capes.*;
import de.winniepat.citrus.cosmetics.capes.sync.CapeSyncManager;
import de.winniepat.citrus.utils.toasts.CustomToast;
import io.wispforest.owo.ui.base.BaseOwoScreen;
import io.wispforest.owo.ui.component.*;
import io.wispforest.owo.ui.container.*;
import io.wispforest.owo.ui.core.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import net.minecraft.util.*;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;

import java.util.*;

public class CapeSelectionScreen extends BaseOwoScreen<FlowLayout> {

    private final Map<String, ButtonComponent> capeButtons = new HashMap<>();

    private LabelComponent statusLabel;
    private LabelComponent currentCapeLabel;
    private LabelComponent capeCountLabel;
    private FlowLayout capeGrid;
    private float updateTimer = 0;

    @Override
    protected @NotNull OwoUIAdapter<FlowLayout> createAdapter() {
        return OwoUIAdapter.create(this, Containers::verticalFlow);
    }

    @Override
    protected void build(FlowLayout root) {
        root.alignment(HorizontalAlignment.CENTER,VerticalAlignment.CENTER);

        FlowLayout main = (FlowLayout) Containers.verticalFlow(Sizing.fixed(350), Sizing.fixed(420))
                .padding(Insets.of(10)).alignment(HorizontalAlignment.CENTER,VerticalAlignment.CENTER);

        FlowLayout content = (FlowLayout) Containers.verticalFlow(Sizing.fill(100), Sizing.content())
                .gap(6)
                .padding(Insets.of(8))
                .surface(Surface.DARK_PANEL);

        FlowLayout currentRow = (FlowLayout) Containers.horizontalFlow(Sizing.fill(100), Sizing.content())
                .gap(6)
                .horizontalAlignment(HorizontalAlignment.CENTER);
        currentRow.child(Components.label(Text.literal("Current:").formatted(Formatting.BOLD)));
        currentCapeLabel = Components.label(Text.literal("None"));
        currentRow.child(currentCapeLabel);
        content.child(currentRow);

        FlowLayout statusRow = (FlowLayout) Containers.horizontalFlow(Sizing.fill(100), Sizing.content())
                .gap(6)
                .horizontalAlignment(HorizontalAlignment.CENTER);
        statusRow.child(Components.label(Text.literal("Status:").formatted(Formatting.BOLD)));
        statusLabel = Components.label(Text.literal("Checking..."));
        statusRow.child(statusLabel);
        content.child(statusRow);

        FlowLayout countRow = (FlowLayout) Containers.horizontalFlow(Sizing.fill(100), Sizing.content())
                .gap(6)
                .horizontalAlignment(HorizontalAlignment.CENTER);
        countRow.child(Components.label(Text.literal("Available:").formatted(Formatting.BOLD)));
        capeCountLabel = Components.label(Text.literal("0"));
        countRow.child(capeCountLabel);
        content.child(countRow);


        capeGrid = (FlowLayout) Containers.verticalFlow(Sizing.fill(100), Sizing.content())
                .gap(6)
                .padding(Insets.of(4));

        var scroll = Containers.verticalScroll(
                Sizing.fill(100),
                Sizing.fixed(180),
                capeGrid
        );

        content.child(scroll);
        main.child(content);
        root.child(main);

        updateStatus();
        populateCapeGrid();
    }

    private void populateCapeGrid() {
        capeGrid.clearChildren();
        capeButtons.clear();

        var capes = CapeHandler.getAvailableCapes();
        var client = MinecraftClient.getInstance();
        if (client.world == null || client.player == null) return;

        capeCountLabel.text(Text.literal(String.valueOf(capes.size())));

        if (capes.isEmpty()) {
            capeGrid.child(Components.label(Text.literal("No capes available")).horizontalSizing(Sizing.fill(100)));
            return;
        }

        int perRow = 3;
        FlowLayout row = null;
        int i = 0;

        for (String cape : capes) {
            if (i++ % perRow == 0) {
                row = Containers.horizontalFlow(Sizing.fill(100), Sizing.content()).gap(8);
                capeGrid.child(row);
            }

            FlowLayout capeEntry = Containers.verticalFlow(Sizing.fixed(100), Sizing.content());
            capeEntry
                    .gap(4)
                    .horizontalAlignment(HorizontalAlignment.CENTER)
                    .padding(Insets.bottom(20));

            Identifier textureId = Identifier.of("citrus", "capes/" + cape);

            var preview = Components.texture(textureId, 0, 0, 64, 32, 64, 32)
                    .sizing(Sizing.fixed(80), Sizing.fixed(40));

            preview.tooltip(Text.literal(cape));

            ButtonComponent button = (ButtonComponent) Components.button(
                    Text.literal(capitalizeFirst(formatCapeName(cape))),
                    b -> equipCape(cape)
            ).horizontalSizing(Sizing.fixed(100)).verticalSizing(Sizing.fixed(20));

            capeButtons.put(cape, button.renderer(
                    ButtonComponent.Renderer.flat(
                            0x5FFFFFFF,
                            0x8FFFFFFF,
                            0x1FFFFFFF
                    ))
            );

            capeEntry.child(preview);
            capeEntry.child(button);
            row.child(capeEntry);

            if (!CapeHandler.isCapeLoaded(cape)) {
                CapeHandler.preloadSpecificCapes(Collections.singletonList(cape));
            }
        }

        updateAllButtonStates();
    }

    @Override
    public void render(DrawContext context, int mouseX, int mouseY, float delta) {
        super.render(context, mouseX, mouseY, delta);

        updateTimer += delta;
        if (updateTimer > 10) {
            updateAllButtonStates();
            updateTimer = 0;
        }
    }

    private String formatCapeName(String name) {
        name = name.replace("_", " ");
        return name.length() > 10 ? name.substring(0, 10) + ".." : name;
    }

    private void equipCape(String cape) {
        if (!CapeHandler.capeExists(cape)) return;

        if ("failed".equals(CapeHandler.getCapeStatus(cape))) {
            setStatusMessage("§cFailed to load cape!");
            return;
        }

        CapeHandler.setLocalPlayerCape(cape, false);
        updateCurrentCapeDisplay();
        CustomToast.sendCustomToast("Equipped Cape", 0xFF55FF55, "You equipped cape " + capitalizeFirst(cape), 0xFFBBBBBB);
        updateAllButtonStates();
    }

    private void updateStatus() {
        CapeSyncManager.checkServerHealth().thenAccept(ok ->
                MinecraftClient.getInstance().execute(() ->
                        setStatusMessage(ok ? "Server online" : "Server offline")
                )
        );
        updateCurrentCapeDisplay();
    }

    private void updateCurrentCapeDisplay() {
        String cape = CapeHandler.getCurrentCapeForLocalPlayer();
        currentCapeLabel.text(Text.literal(
                cape == null || "none".equals(cape) ? "None" :
                        "auto".equals(cape) ? "Auto" : cape
        ));
    }

    private void updateAllButtonStates() {
        String current = CapeHandler.getCurrentCapeForLocalPlayer();

        for (var entry : capeButtons.entrySet()) {
            String capeName = entry.getKey();
            var status = CapeHandler.getCapeStatus(capeName);

            boolean isEquipped = capeName.equals(current);

            entry.getValue().active(!isEquipped);

            if ("failed".equals(status)) {
                entry.getValue().setMessage(Text.literal("Error").formatted(Formatting.RED));
            } else if ("loading".equals(status)) {
                entry.getValue().setMessage(Text.literal("Loading...").formatted(Formatting.YELLOW));
            } else {
                entry.getValue().setMessage(Text.literal(capitalizeFirst(formatCapeName(capeName))));
            }
        }
    }

    private void setStatusMessage(String msg) {
        statusLabel.text(Text.literal(msg));
    }

    public static String capitalizeFirst(String text) {
        return text == null || text.isEmpty()
                ? text
                : text.substring(0, 1).toUpperCase(Locale.ROOT)
                + text.substring(1).toLowerCase(Locale.ROOT);
    }

    @Override
    public boolean keyPressed(int key, int scancode, int mods) {
        if (key == GLFW.GLFW_KEY_ESCAPE) {
            close();
            return true;
        }
        return super.keyPressed(key, scancode, mods);
    }

    @Override
    public void close() {
        assert client != null;
        client.setScreen(null);
    }
}