#pragma once

#include "lumacs/editor_core.hpp"
#include "lumacs/theme.hpp"
#include "lumacs/keybinding.hpp"
#include <sol/sol.hpp>
#include <functional>
#include <map>
#include <string>

namespace lumacs {

class EditorCore; // Forward declaration

/// @brief Bridge between C++ Core and Lua 5.4 environment.
/// 
/// The LuaApi class is responsible for:
/// - Initializing the Lua virtual machine.
/// - Exposing C++ types (Buffer, Window, etc.) to Lua.
/// - Exposing C++ functions/commands to Lua.
/// - Loading and executing user configuration scripts (init.lua).
/// - Managing the interaction between Lua scripts and the EditorCore.
class LuaApi {
public:
    /// @brief Construct the Lua API bridge.
    explicit LuaApi();
    ~LuaApi() = default;

    /// @brief Connect the API to the EditorCore instance.
    /// @param core The editor core instance.
    void set_core(EditorCore& core);

    /// @brief Get the underlying Lua state object (sol2).
    [[nodiscard]] sol::state_view& get_lua_state() { return lua_; }

    /// @brief Load and execute a Lua file from disk.
    /// @param path The path to the Lua file.
    /// @return true if loaded and executed successfully.
    bool load_file(const std::filesystem::path& path);

    /// @brief Execute a string of Lua code.
    /// @param code The Lua code to execute.
    /// @return true if executed successfully.
    bool execute(std::string_view code);

    /// @brief Attempt to find and load the user's 'init.lua'.
    /// Checks standard locations (e.g., ~/.config/lumacs/init.lua).
    /// @return true if found and loaded.
    bool load_init_file();

    /// @brief Bind a key sequence to a Lua function.
    /// @param key The key sequence (e.g., "C-x C-f").
    /// @param callback The Lua function to call.
    /// @param description Optional description for the binding.
    void bind_key(std::string key, sol::function callback, std::string description = "");

    /// @brief Process a key press via the Lua layer/KeyBindingManager.
    /// @param key The key name/sequence.
    /// @return The result of processing (Unbound, Executed, etc.).
    KeyProcessingResult process_key(const std::string& key); // Changed return type

    /// @brief Get all registered Lua key bindings (Legacy).
    [[nodiscard]] std::map<std::string, sol::function> key_bindings() const {
        return legacy_key_bindings_;
    }

    bool execute_key_binding(const std::string& key);

    // New manual functions for core interactions
    int get_active_buffer_line_count_lua();
    void lua_editor_move_right();
    void lua_editor_new_buffer(const std::string& name);
    sol::optional<std::string> lua_editor_get_buffer_by_name(const std::string& name);
    void lua_editor_set_message(const std::string& message);
    void lua_config_set_string(const std::string& key, const std::string& value);
    std::string lua_config_get_string(const std::string& key, const std::string& default_val);
    void lua_config_set_bool(const std::string& key, bool value);
    bool lua_config_get_bool(const std::string& key, bool default_val);
    void lua_config_set_int(const std::string& key, int value);
    int lua_config_get_int(const std::string& key, int default_val);

    // Legacy methods for backward compatibility
    [[nodiscard]] bool has_key_binding(const std::string& key) const;

private:
    sol::state lua_;
    EditorCore* core_ = nullptr; 
    std::map<std::string, sol::function> legacy_key_bindings_;  // For backward compatibility

    /// Initialize Lua state and libraries.
    void setup_api();
    
    /// Register C++ user types (usertypes) with Sol2.
    void register_types();
    
    /// Register global C++ functions in Lua.
    void register_functions();
};

} // namespace lumacs
