#pragma once

#include <cstddef>
#include <nlohmann/json.hpp>
#include <string>
#include <vector>

namespace dragonx {
namespace ui {

struct ConsoleCompletionResult {
    std::vector<std::string> matches;
    std::string commonPrefix;
};

struct ConsoleRpcCall {
    bool valid = false;
    std::string method;
    nlohmann::json params = nlohmann::json::array();
    std::string error;   // set (with valid=false) when an argument fails to parse
};

enum class ConsoleResultLineRole {
    Result,
    Error,
    JsonKey,
    JsonString,
    JsonNumber,
    JsonBrace
};

struct ConsoleResultLine {
    std::string text;
    ConsoleResultLineRole role = ConsoleResultLineRole::Result;
};

const std::vector<std::string>& ConsoleRpcCommandNames();
void AppendConsoleHistory(std::vector<std::string>& history,
                          const std::string& command,
                          std::size_t maxEntries = 100);
int NavigateConsoleHistoryIndex(int currentIndex,
                                std::size_t historySize,
                                bool up);
std::string ConsoleHistoryEntry(const std::vector<std::string>& history,
                                int historyIndex);
ConsoleCompletionResult CompleteConsoleCommand(const std::string& input);
std::vector<std::string> FormatConsoleCompletionLines(const std::vector<std::string>& matches,
                                                      std::size_t maxLineLength = 60);
// A tokenized console argument. `quoted` is true when the token came from a "..."/'...' literal,
// so BuildConsoleRpcCall must send it verbatim as a JSON string (never coerce it to a number/bool).
struct ConsoleArg {
    std::string text;
    bool quoted = false;
};
std::vector<ConsoleArg> ParseConsoleCommandArgsTagged(const std::string& command);
std::vector<std::string> ParseConsoleCommandArgs(const std::string& command);
ConsoleRpcCall BuildConsoleRpcCall(const std::string& command);
std::vector<ConsoleResultLine> FormatConsoleRpcResultLines(const std::string& result,
                                                           bool isError);

// For a block of pretty-printed JSON lines, return a per-line fold span: for a line that
// opens a collapsible block (its last non-space char is '{' or '[') the value is the offset
// to its matching closing-bracket line at the same indentation; 0 for every other line and
// for empty/one-line blocks not worth folding (span < 2). Pure; used to drive console
// JSON folding.
std::vector<int> ComputeConsoleFoldSpans(const std::vector<std::string>& lines);

} // namespace ui
} // namespace dragonx
