// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#include "address_book_dialog.h"
#include "../../app.h"
#include "../../data/address_book.h"
#include "../../util/i18n.h"
#include "../notifications.h"
#include "../schema/ui_schema.h"
#include "../material/draw_helpers.h"
#include "imgui.h"
#include <cstring>
#include <memory>

namespace dragonx {
namespace ui {

// Static member initialization
bool AddressBookDialog::s_open = false;
int AddressBookDialog::s_selected_index = -1;
bool AddressBookDialog::s_show_add_dialog = false;
bool AddressBookDialog::s_show_edit_dialog = false;
char AddressBookDialog::s_edit_label[128] = "";
char AddressBookDialog::s_edit_address[512] = "";
char AddressBookDialog::s_edit_notes[512] = "";

// Shared address book instance
static std::unique_ptr<data::AddressBook> s_address_book;

static data::AddressBook& getAddressBook() {
    if (!s_address_book) {
        s_address_book = std::make_unique<data::AddressBook>();
        s_address_book->load();
    }
    return *s_address_book;
}

static void copyEditField(char* dest, size_t destSize, const std::string& source) {
    if (destSize == 0) return;
    std::strncpy(dest, source.c_str(), destSize - 1);
    dest[destSize - 1] = '\0';
}

void AddressBookDialog::show()
{
    s_open = true;
    s_selected_index = -1;
    s_show_add_dialog = false;
    s_show_edit_dialog = false;
    
    // Reload address book
    getAddressBook().load();
}

bool AddressBookDialog::isOpen()
{
    return s_open;
}

void AddressBookDialog::render(App* app)
{
    (void)app;  // May use for send-to feature later
    
    if (!s_open) return;

    auto& S = schema::UI();
    auto win = S.window("dialogs.address-book");
    auto addrTable = S.table("dialogs.address-book", "address-table");
    auto addrFrontLbl = S.label("dialogs.address-book", "address-front-label");
    auto addrBackLbl = S.label("dialogs.address-book", "address-back-label");
    auto addrInput = S.input("dialogs.address-book", "address-input");
    auto notesInput = S.input("dialogs.address-book", "notes-input");
    auto actionBtn = S.button("dialogs.address-book", "action-button");

    auto clearEditFields = []() {
        s_edit_label[0] = '\0';
        s_edit_address[0] = '\0';
        s_edit_notes[0] = '\0';
    };

    auto loadEditFields = [](const data::AddressBookEntry& entry) {
        copyEditField(s_edit_label, sizeof(s_edit_label), entry.label);
        copyEditField(s_edit_address, sizeof(s_edit_address), entry.address);
        copyEditField(s_edit_notes, sizeof(s_edit_notes), entry.notes);
    };

    auto renderEntryDialog = [&]() {
        bool isEdit = s_show_edit_dialog;
        bool* open = isEdit ? &s_show_edit_dialog : &s_show_add_dialog;
        if (!*open) return;

        const char* title = isEdit ? TR("address_book_edit") : TR("address_book_add");
        const char* id = isEdit ? "AddressBookEdit" : "AddressBookAdd";
        float dialogW = std::max(Layout::kDialogMinWidth(), Layout::kDialogDefaultWidth());
        float formW = addrInput.width > 0 ? addrInput.width : Layout::kDialogFormWidth();
        float actionW = actionBtn.width > 0 ? actionBtn.width : Layout::kDialogActionWidth();
        float actionGap = actionBtn.gap > 0 ? actionBtn.gap : Layout::kDialogActionGap();
        float notesH = notesInput.height > 0 ? notesInput.height : 60.0f;

        if (material::BeginOverlayDialog(title, open, dialogW, 0.94f,
                                         Layout::kDialogCompactBottomRatio(), id)) {
            ImGui::Text("%s", TR("label"));
            ImGui::SetNextItemWidth(formW);
            ImGui::InputText(isEdit ? "##EditLabel" : "##AddLabel", s_edit_label, sizeof(s_edit_label));

            ImGui::Spacing();

            ImGui::Text("%s", TR("address_label"));
            ImGui::SetNextItemWidth(formW);
            ImGui::InputText(isEdit ? "##EditAddress" : "##AddAddress", s_edit_address, sizeof(s_edit_address));
            if (!isEdit) {
                ImGui::SameLine();
                if (material::StyledButton(TR("paste"), ImVec2(0,0), S.resolveFont(actionBtn.font))) {
                    const char* clipboard = ImGui::GetClipboardText();
                    if (clipboard) copyEditField(s_edit_address, sizeof(s_edit_address), clipboard);
                }
            }

            ImGui::Spacing();

            ImGui::Text("%s", TR("notes_optional"));
            ImGui::SetNextItemWidth(formW);
            ImGui::InputTextMultiline(isEdit ? "##EditNotes" : "##AddNotes",
                                      s_edit_notes, sizeof(s_edit_notes), ImVec2(formW, notesH));

            bool canSubmit = std::strlen(s_edit_label) > 0 && std::strlen(s_edit_address) > 0;
            float totalActionsW = actionW * 2.0f + actionGap;
            material::BeginOverlayDialogFooter(totalActionsW);

            if (!canSubmit) ImGui::BeginDisabled();

            const char* primaryLabel = isEdit ? TR("save") : TR("add");
            if (material::StyledButton(primaryLabel, ImVec2(actionW, 0), S.resolveFont(actionBtn.font))) {
                data::AddressBookEntry entry(s_edit_label, s_edit_address, s_edit_notes);
                if (isEdit) {
                    if (getAddressBook().updateEntry(s_selected_index, entry)) {
                        Notifications::instance().success(TR("address_book_updated"));
                        s_show_edit_dialog = false;
                    } else {
                        Notifications::instance().error(TR("address_book_update_failed"));
                    }
                } else {
                    if (getAddressBook().addEntry(entry)) {
                        Notifications::instance().success(TR("address_book_added"));
                        s_show_add_dialog = false;
                    } else {
                        Notifications::instance().error(TR("address_book_exists"));
                    }
                }
            }

            if (!canSubmit) ImGui::EndDisabled();

            ImGui::SameLine(0, actionGap);
            if (material::StyledButton(TR("cancel"), ImVec2(actionW, 0), S.resolveFont(actionBtn.font))) {
                *open = false;
            }

            material::EndOverlayDialog();
        }
    };

    if (material::BeginOverlayDialog(TR("address_book_title"), &s_open, win.width, 0.94f)) {
        auto& book = getAddressBook();
        
        // Toolbar
        if (material::StyledButton(TR("address_book_add_new"), ImVec2(0,0), S.resolveFont(actionBtn.font))) {
            s_show_add_dialog = true;
            clearEditFields();
        }
        
        ImGui::SameLine();
        
        bool has_selection = s_selected_index >= 0 && s_selected_index < static_cast<int>(book.size());
        
        if (!has_selection) ImGui::BeginDisabled();
        
        if (material::StyledButton(TR("edit"), ImVec2(0,0), S.resolveFont(actionBtn.font))) {
            if (has_selection) {
                const auto& entry = book.entries()[s_selected_index];
                loadEditFields(entry);
                s_show_edit_dialog = true;
            }
        }
        
        ImGui::SameLine();
        
        if (material::StyledButton(TR("delete"), ImVec2(0,0), S.resolveFont(actionBtn.font))) {
            if (has_selection) {
                book.removeEntry(s_selected_index);
                s_selected_index = -1;
                Notifications::instance().success(TR("address_book_deleted"));
            }
        }
        
        ImGui::SameLine();
        
        if (material::StyledButton(TR("copy_address"), ImVec2(0,0), S.resolveFont(actionBtn.font))) {
            if (has_selection) {
                ImGui::SetClipboardText(book.entries()[s_selected_index].address.c_str());
                Notifications::instance().info(TR("address_copied"));
            }
        }
        
        if (!has_selection) ImGui::EndDisabled();
        
        ImGui::Spacing();
        ImGui::Separator();
        ImGui::Spacing();
        
        // Address list
        if (ImGui::BeginTable("AddressBookTable", 3,
            ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
            ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY,
            ImVec2(0, addrTable.bottomReserve > 0 ? -addrTable.bottomReserve : -35)))
        {
            float labelColW = (addrTable.columns.count("label") && addrTable.columns.at("label").width > 0) ? addrTable.columns.at("label").width : 150;
            float notesColW = (addrTable.columns.count("notes") && addrTable.columns.at("notes").width > 0) ? addrTable.columns.at("notes").width : 150;
            ImGui::TableSetupColumn(TR("label"), ImGuiTableColumnFlags_WidthFixed, labelColW);
            ImGui::TableSetupColumn(TR("address_label"), ImGuiTableColumnFlags_WidthStretch);
            ImGui::TableSetupColumn(TR("notes"), ImGuiTableColumnFlags_WidthFixed, notesColW);
            ImGui::TableSetupScrollFreeze(0, 1);
            ImGui::TableHeadersRow();
            
            if (book.empty()) {
                ImGui::TableNextRow();
                ImGui::TableNextColumn();
                ImGui::TextDisabled("%s", TR("address_book_empty"));
            } else {
                for (size_t i = 0; i < book.size(); i++) {
                    const auto& entry = book.entries()[i];
                    
                    ImGui::TableNextRow();
                    ImGui::PushID(static_cast<int>(i));
                    
                    ImGui::TableNextColumn();
                    bool is_selected = (s_selected_index == static_cast<int>(i));
                    if (ImGui::Selectable(entry.label.c_str(), is_selected, 
                                          ImGuiSelectableFlags_SpanAllColumns)) {
                        s_selected_index = static_cast<int>(i);
                    }
                    
                    // Double-click to edit
                    if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
                        s_selected_index = static_cast<int>(i);
                        loadEditFields(entry);
                        s_show_edit_dialog = true;
                    }
                    
                    ImGui::TableNextColumn();
                    // Truncate long addresses
                    std::string addr_display = entry.address;
                    int addrTruncLen = (addrTable.columns.count("address") && addrTable.columns.at("address").truncate > 0) ? addrTable.columns.at("address").truncate : 40;
                    if (addr_display.length() > static_cast<size_t>(addrTruncLen)) {
                        addr_display = addr_display.substr(0, addrFrontLbl.truncate) + "..." + 
                                       addr_display.substr(addr_display.length() - addrBackLbl.truncate);
                    }
                    ImGui::TextDisabled("%s", addr_display.c_str());
                    if (ImGui::IsItemHovered()) {
                        material::Tooltip("%s", entry.address.c_str());
                    }
                    
                    ImGui::TableNextColumn();
                    ImGui::TextDisabled("%s", entry.notes.c_str());
                    
                    ImGui::PopID();
                }
            }
            
            ImGui::EndTable();
        }
        
        // Status line
        ImGui::TextDisabled(TR("address_book_count"), book.size());
        material::EndOverlayDialog();
    }

    renderEntryDialog();
}

} // namespace ui
} // namespace dragonx
