package cz.jzitnik.game.ui;

import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal;

import cz.jzitnik.game.Game;
import cz.jzitnik.game.sprites.ui.Font;
import cz.jzitnik.game.sprites.ui.Font.Align;
import cz.jzitnik.game.sprites.ui.Font.Background;
import cz.jzitnik.game.sprites.ui.Font.Custom;
import cz.jzitnik.game.sprites.ui.Font.Size;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.extern.slf4j.Slf4j;

/**
 * Displays the death screen UI with a "You Died" message and a respawn button.
 * Handles rendering and mouse interactions for the respawn action.
 */
@Slf4j
public class DeathScreen {
    private int btnWidth;
    private int leftPad;
    private int mainTextHeight;
    private int buttonHeight;
    private int textButtonMargin;
    private boolean buttonHover;

    /**
     * Renders the death screen with a heading and the respawn button.
     *
     * @param buffer   The rendering buffer.
     * @param terminal The terminal to determine size and dimensions.
     * @param game     The game instance for accessing dependencies.
     */
    public void render(StringBuilder buffer, Terminal terminal, Game game) {
        log.debug("Rendering death screen");
        var font = game.getGameStates().dependencies.font;
        var width = terminal.getWidth();
        var height = terminal.getHeight();

        var heading = font.line(terminal, "You Died", Size.LARGE, Align.CENTER);

        buffer.append(heading.getData());

        textButtonMargin = (height < 600) ? 15 : (height < 800) ? 30 : 50;
        buffer.append("\n".repeat(textButtonMargin));

        renderButton(buffer, "Respawn", width, font, terminal, buttonHover);
    }

    /**
     * Renders a single button with hover state and styling.
     *
     * @param buffer   The rendering buffer.
     * @param txt      The text to display in the button.
     * @param width    The terminal width for calculating centering.
     * @param font     The font renderer.
     * @param terminal The terminal object.
     * @param selected Whether the button is currently hovered.
     */
    public void renderButton(StringBuilder buffer, String txt, int width, Font font, Terminal terminal,
            boolean selected) {
        btnWidth = Math.min(350, (int) (width * (3.0 / 4)));
        leftPad = (width - btnWidth) / 2;
        log.debug("Button width: {}px ", btnWidth);

        final String color = selected ? "[48;2;70;70;70m" : "[48;2;116;115;113m";
        var text = font.line(terminal, txt, Size.SMALL, Align.CENTER, new Custom.Width(btnWidth - 4),
                new Background(color));
        buttonHeight = text.getHeight() + 4;
        var lines = text.getData().split("\n");

        for (int y = 0; y < buttonHeight; y++) {
            buffer.append(" ".repeat(leftPad));
            if (y < 2 || y >= buttonHeight - 2) {
                buffer.append("\033").append(color).append(" ".repeat(btnWidth));
            } else {
                buffer.append("\033").append(color).append(" ".repeat(2));
                buffer.append(lines[y - 2]);
                buffer.append("\033").append(color).append(" ".repeat(2));
            }
            buffer.append("\033[0m\n");
        }
    }

    /**
     * Handles mouse interactions for the death screen, including hover and click
     * detection on the "Respawn" button.
     *
     * @param mouseEvent     The mouse event that occurred.
     * @param terminal       The terminal used for dimensions.
     * @param screenRenderer The screen renderer to trigger re-renders.
     * @param game           The game instance to change state upon respawn.
     */
    public void handleMouse(MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer, Game game) {
        int x = mouseEvent.getX();
        int y = mouseEvent.getY();
        var type = mouseEvent.getType();

        int buttonx = x - leftPad;
        int buttony = y - (mainTextHeight + textButtonMargin) - 2;
        int margin = textButtonMargin / 2;

        boolean changed = false;

        if (buttonx > 0 && buttonx <= btnWidth) {
            int top = (buttonHeight + margin);
            int bottom = top + buttonHeight;

            if (buttony > top && buttony < bottom) {
                if (type == MouseEvent.Type.Pressed) {
                    game.setWindow(Window.WORLD);
                    game.getPlayer().resetHealth();
                    game.getPlayer().resetHunger();
                    screenRenderer.render(game);
                    return;
                }
                if (!buttonHover) {
                    buttonHover = true;
                    changed = true;
                }
            } else if (buttonHover) {
                buttonHover = false;
                changed = true;
            }
        }

        if (changed) {
            screenRenderer.render(game);
        }
    }
}
