#include "lumacs/minibuffer_manager.hpp"
#include "lumacs/editor_core.hpp" // For EditorCore interaction
#include "lumacs/lua_api.hpp"     // For LuaApi interaction
#include "lumacs/minibuffer_mode_hash.hpp" // New include for MinibufferMode hash
#include "lumacs/completion_system.hpp" // Include for CompletionSystem
#include "lumacs/command_system.hpp" // For Command and CommandSystem
#include <functional> // Required for std::function
#include <sstream>    // For parsing command line

#include <iostream> // TODO: Replace with proper logging

namespace lumacs {

MinibufferManager::MinibufferManager(EditorCore& core, LuaApi& lua_api, CompletionSystem& completion_system)
    : core_(core), lua_api_(lua_api), completion_system_(completion_system), isearch_manager_(core) {
    // Initialize history managers for each mode
    histories_[MinibufferMode::Command] = HistoryManager();
    histories_[MinibufferMode::FilePath] = HistoryManager();
    histories_[MinibufferMode::BufferName] = HistoryManager();
    histories_[MinibufferMode::ThemeName] = HistoryManager();
    histories_[MinibufferMode::ISearch] = HistoryManager();
    histories_[MinibufferMode::ystring] = HistoryManager();
    histories_[MinibufferMode::y_or_n_p] = HistoryManager();
}

void MinibufferManager::activate_minibuffer(MinibufferMode mode, const std::string& prompt,
                                             std::function<void(const std::string&)> on_submit,
                                             std::function<void()> on_cancel) {
    current_mode_ = mode;
    prompt_text_ = prompt;
    input_buffer_ = ""; // Clear previous input
    on_submit_callback_ = on_submit;
    on_cancel_callback_ = on_cancel;
    cursor_position_ = 0; // Initialize cursor position

    // Set current history manager based on mode
    current_history_ = &histories_[mode];

    // Initialize ISearch via ISearchManager
    if (mode == MinibufferMode::ISearch) {
        isearch_manager_.set_prompt(prompt);
        isearch_manager_.start(true); // Default to forward search
    }

    update_completion_candidates();
}

void MinibufferManager::deactivate_minibuffer() {
    // Stop ISearch if active (without restoring cursor - user confirmed the match)
    if (isearch_manager_.is_active()) {
        isearch_manager_.stop(false);
    }

    current_mode_ = MinibufferMode::None;
    prompt_text_ = "";
    input_buffer_ = "";
    on_submit_callback_ = nullptr;
    on_cancel_callback_ = nullptr;
    current_history_ = nullptr; // Clear current history pointer
    completion_candidates_.clear();
    completion_index_ = 0;
    cursor_position_ = 0; // Reset cursor position
}

bool MinibufferManager::handle_key_event(const std::string& key_name) {
    if (current_mode_ == MinibufferMode::None) {
        return false; // Minibuffer not active
    }

    if (current_mode_ == MinibufferMode::ISearch) {
        if (key_name == "Return") {
            isearch_manager_.stop(false); // Keep cursor at match
            deactivate_minibuffer();
            return true;
        } else if (key_name == "Escape") {
            isearch_manager_.stop(true); // Restore cursor to start position
            deactivate_minibuffer();
            return true;
        } else if (key_name == "C-s") {
            // Next match (forward)
            isearch_manager_.set_direction(true);
            isearch_manager_.next_match();
            return true;
        } else if (key_name == "C-r") {
            // Previous match (backward)
            isearch_manager_.set_direction(false);
            isearch_manager_.previous_match();
            return true;
        } else if (key_name == "Backspace") {
            if (cursor_position_ > 0) {
                input_buffer_.erase(cursor_position_ - 1, 1);
                cursor_position_--;
                isearch_manager_.update(input_buffer_);
            } else {
                // If query is empty, cancel ISearch.
                isearch_manager_.stop(true);
                deactivate_minibuffer();
            }
            return true;
        } else if (key_name.length() == 1) { // Regular character input
            input_buffer_.insert(cursor_position_, key_name);
            cursor_position_++;
            isearch_manager_.update(input_buffer_);
            return true;
        }
        // If other keys are pressed in ISearch mode, they are usually treated as part of the query.
        // For now, if not specifically handled, ignore them.
        return false;
    }

    if (current_mode_ == MinibufferMode::y_or_n_p) {
        if (key_name == "y" || key_name == "Y") {
            if (on_submit_callback_) on_submit_callback_("y");
            deactivate_minibuffer();
            return true;
        } else if (key_name == "n" || key_name == "N") {
            if (on_submit_callback_) on_submit_callback_("n");
            deactivate_minibuffer();
            return true;
        } else if (key_name == "Escape" || key_name == "C-g") {
             if (on_cancel_callback_) on_cancel_callback_();
             deactivate_minibuffer();
             return true;
        }
        // Ignore other keys
        return true;
    }

    // --- Generic Minibuffer Handling (for other modes) ---
    if (key_name == "Return") {
        add_to_history();
        if (on_submit_callback_) {
            on_submit_callback_(input_buffer_);
        }
        deactivate_minibuffer();
        return true;
    } else if (key_name == "Escape") {
        if (on_cancel_callback_) {
            on_cancel_callback_();
        }
        deactivate_minibuffer();
        return true;
    } else if (key_name == "Backspace") {
        if (cursor_position_ > 0) {
            input_buffer_.erase(cursor_position_ - 1, 1);
            cursor_position_--;
            update_completion_candidates(); // Update completions on backspace
        }
        return true;
    } else if (key_name == "Delete") {
        if (cursor_position_ < input_buffer_.length()) {
            input_buffer_.erase(cursor_position_, 1);
            update_completion_candidates(); // Update completions on delete
        }
        return true;
    } else if (key_name == "Left" || key_name == "ArrowLeft") {
        if (cursor_position_ > 0) {
            cursor_position_--;
        }
        return true;
    } else if (key_name == "Right" || key_name == "ArrowRight") {
        if (cursor_position_ < input_buffer_.length()) {
            cursor_position_++;
        }
        return true;
    } else if (key_name == "Home") {
        cursor_position_ = 0;
        return true;
    } else if (key_name == "End") {
        cursor_position_ = input_buffer_.length();
        return true;
    } else if (key_name == "Tab") {
        complete();
        return true;
    } else if (key_name == "C-p" || key_name == "ArrowUp") { // Previous history
        history_previous();
        return true;
    } else if (key_name == "C-n" || key_name == "ArrowDown") { // Next history
        history_next();
        return true;
    } else if (key_name.length() == 1) { // Regular character input
        input_buffer_.insert(cursor_position_, key_name);
        cursor_position_++;
        update_completion_candidates(); // Update completions on new input
        return true;
    }
    return false; 
}

std::string MinibufferManager::get_prompt() const {
    return prompt_text_;
}

std::string MinibufferManager::get_input_buffer() const {
    return input_buffer_;
}

size_t MinibufferManager::get_cursor_position() const {
    return cursor_position_;
}

void MinibufferManager::set_input_buffer(const std::string& input) {
    input_buffer_ = input;
    cursor_position_ = input_buffer_.length();
    update_completion_candidates();
}

void MinibufferManager::add_to_history() {
    if (current_history_) {
        current_history_->add_item(input_buffer_);
    }
}

void MinibufferManager::history_previous() {
    if (current_history_) {
        input_buffer_ = current_history_->previous();
        cursor_position_ = input_buffer_.length(); // Move cursor to end of history item
        update_completion_candidates();
    }
}

void MinibufferManager::history_next() {
    if (current_history_) {
        input_buffer_ = current_history_->next();
        cursor_position_ = input_buffer_.length(); // Move cursor to end of history item
        update_completion_candidates();
    }
}

void MinibufferManager::update_completion_candidates() {
    completion_candidates_.clear();
    completion_index_ = 0;

    if (input_buffer_.empty()) {
        return;
    }

    completion_candidates_ = completion_system_.get_candidates_for_mode(current_mode_, input_buffer_);
}

std::vector<CompletionCandidate> MinibufferManager::get_completion_candidates() const {
    return completion_candidates_;
}

std::optional<std::string> MinibufferManager::get_current_completion() const {
    if (!completion_candidates_.empty()) {
        return completion_candidates_[completion_index_].text;
    }
    return std::nullopt;
}

void MinibufferManager::complete() {
    if (!completion_candidates_.empty()) {
        input_buffer_ = completion_candidates_[completion_index_].text;
        cursor_position_ = input_buffer_.length(); // Update cursor position
        completion_index_ = (completion_index_ + 1) % completion_candidates_.size();
        // If we cycle, reset the index so next tab starts from the top.
        // Or, more Emacs-like, cycle through the list and if we get back to original,
        // stay there until new input. For now, simple cycle.
    }
}

CommandResult MinibufferManager::parse_and_execute_command_string(const std::string& command_line) {
    std::string command_name;
    std::vector<std::string> args;
    std::stringstream ss(command_line);
    
    ss >> command_name; // Extract command name

    std::string arg;
    while (ss >> arg) { // Extract arguments
        args.push_back(arg);
    }

    // Directly execute the command. If the command is interactive and needs more arguments,
    // the execute method will return PendingInput. This assumes the caller (e.g., Lua API)
    // will know how to handle CommandStatus::PendingInput if it tries to execute an
    // interactive command that requires more input than provided in the string.
    // However, for typical Lua API calls, commands are expected to be fully specified.
    return core_.command_system().execute(command_name, args);
}

// === ISearch Implementations ===

void MinibufferManager::start_isearch(bool forward) {
    if (current_mode_ != MinibufferMode::ISearch) {
        // This should be called only when ISearch mode is active
        return;
    }
    isearch_manager_.set_direction(forward);
}

} // namespace lumacs