#include "presentation/pages/items/ItemsPage.h"

#include <algorithm>
#include <array>
#include <string>
#include <utility>
#include <vector>

#include <imgui.h>
#include <imgui_stdlib.h>

#include "foundation/text/StringUtils.h"
#include "presentation/localization/UiLocalizationService.h"
#include "foundation/diagnostics/ExecutionPath.h"
#include "presentation/action_feedback/ActionFeedbackPresenter.h"
#include "presentation/runtime/Viewport.h"
#include "presentation/theme/MenuTheme.h"
#include "presentation/widgets/BasicWidgets.h"
#include "presentation/widgets/ConfigWidgets.h"
#include "presentation/config/ConfigSnapshotLookup.h"

namespace ta::presentation::pages::items
{
    namespace
    {
        using ItemEntry = ta::features::items::contracts::ItemCatalogEntry;
        using ItemSnapshot = ta::features::items::contracts::ItemCatalogSnapshot;

        constexpr std::array<const char*, 11> category_labels = {{
            "All Categories",
            "Weapons",
            "Ammunition",
            "Weapon Mods",
            "Equipment",
            "Medical Items",
            "Diet",
            "Keys",
            "Containers",
            "Trade Goods",
            "Other Items"
        }};

        const ConfigPanelSnapshot* find_item_panel(const MenuContext& context)
        {
            if (!context.config)
                return nullptr;
            const auto found = std::find_if(context.config->panels.begin(), context.config->panels.end(), [](const ConfigPanelSnapshot& panel)
            {
                return panel.id == "item";
            });
            return found == context.config->panels.end() ? nullptr : &*found;
        }

        using ta::presentation::config_snapshot::find_value;

        std::string trim(std::string value)
        {
            return ta::foundation::text::trim_copy(value);
        }

        void submit_config_value(const ItemsPageContext& context,
                                 const ConfigValueSnapshot& value,
                                 ta::application::config::ConfigValueData data)
        {
            if (context.submit_config && value.valid())
            {
                context.submit_config({
                    ConfigCommandType::SetValue,
                    value.key,
                    std::move(data)
                });
            }
        }

        void request_catalog_reload(const ItemsPageContext& context)
        {
            if (!context.commands)
                return;

            ta::features::items::contracts::ItemSelectorCommand command{
                ta::features::items::contracts::ItemSelectorCommandType::ReloadCatalog,
                false,
                0
            };
            context.commands->submit_selector(std::move(command));
        }

        void request_item_action(const ItemsPageContext& context,
                                 const ta::features::items::contracts::PendingAction action)
        {
            if (!context.in_raid || !context.commands)
                return;

            ta::features::items::contracts::ItemActionCommand command{};
            command.action = action;
            command.trace_id = ActionFeedbackPresenter::begin(
                ActionFeedbackPresenter::item_action_key(action),
                ta::presentation::localization::tr(std::string(ta::features::items::contracts::to_string(action))),
                "Items");
            ta::foundation::execution_path::step(command.trace_id, "ItemsPage", "submit item action");
            context.commands->request_action(std::move(command));
        }

        void draw_category_filter(ItemCatalogModel& model)
        {
            int selected = (std::clamp)(model.category_filter(), 0, static_cast<int>(category_labels.size()) - 1);
            const std::string preview = ta::presentation::localization::tr(category_labels[static_cast<std::size_t>(selected)]);
            ImGui::SetNextItemWidth(-1.0f);
            if (ImGui::BeginCombo("##item_category_filter", preview.c_str()))
            {
                for (std::size_t index = 0; index < category_labels.size(); ++index)
                {
                    const bool active = static_cast<int>(index) == selected;
                    const std::string label = ta::presentation::localization::tr(category_labels[index]) + "##category_" + std::to_string(index);
                    if (ImGui::Selectable(label.c_str(), active))
                        model.category_filter() = static_cast<int>(index);
                    if (active)
                        ImGui::SetItemDefaultFocus();
                }
                ImGui::EndCombo();
            }
        }

        void draw_workspace_toolbar(const ItemsPageContext& context,
                                    ItemCatalogModel& model,
                                    const ItemSnapshot& snapshot,
                                    const ConfigValueSnapshot& item_id)
        {
            const float scale = ta::presentation::runtime::scale_factor();
            const bool compact = ImGui::GetContentRegionAvail().x < 760.0f * scale;

            if (compact)
            {
                ImGui::SetNextItemWidth(-1.0f);
                ImGui::InputTextWithHint(
                    "##item_search",
                    ta::presentation::localization::tr("Search items by name or ID").c_str(),
                    &model.search());

                draw_category_filter(model);
                if (ImGui::BeginTable("##item_workspace_toolbar_compact", 2,
                                      ImGuiTableFlags_SizingStretchSame |
                                      ImGuiTableFlags_NoSavedSettings))
                {
                    ImGui::TableNextColumn();
                    ImGui::Checkbox(ta::presentation::localization::tr("Wishlist only").c_str(), &model.wishlist_only());
                    ImGui::TableNextColumn();
                    ImGui::BeginDisabled(!context.in_raid);
                    if (ta::presentation::widgets::action_button(ta::presentation::localization::tr("Reload catalog"), 145.0f, 92.0f))
                        request_catalog_reload(context);
                    ImGui::EndDisabled();
                    ImGui::EndTable();
                }
            }
            else if (ImGui::BeginTable("##item_workspace_toolbar", 4,
                                       ImGuiTableFlags_SizingStretchProp |
                                       ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableSetupColumn("##search", ImGuiTableColumnFlags_WidthStretch, 0.52f);
                ImGui::TableSetupColumn("##category", ImGuiTableColumnFlags_WidthFixed, 190.0f * scale);
                ImGui::TableSetupColumn("##wishlist", ImGuiTableColumnFlags_WidthFixed, 120.0f * scale);
                ImGui::TableSetupColumn("##reload", ImGuiTableColumnFlags_WidthFixed, 145.0f * scale);
                ImGui::TableNextRow();

                ImGui::TableSetColumnIndex(0);
                ImGui::SetNextItemWidth(-1.0f);
                ImGui::InputTextWithHint(
                    "##item_search",
                    ta::presentation::localization::tr("Search items by name or ID").c_str(),
                    &model.search());

                ImGui::TableSetColumnIndex(1);
                draw_category_filter(model);

                ImGui::TableSetColumnIndex(2);
                ImGui::Checkbox(ta::presentation::localization::tr("Wishlist only").c_str(), &model.wishlist_only());

                ImGui::TableSetColumnIndex(3);
                ImGui::BeginDisabled(!context.in_raid);
                if (ta::presentation::widgets::action_button(ta::presentation::localization::tr("Reload catalog"), 145.0f, 112.0f))
                    request_catalog_reload(context);
                ImGui::EndDisabled();
                ImGui::EndTable();
            }

            const std::string entered = trim(model.search());
            if (!entered.empty())
            {
                if (ta::presentation::widgets::action_button(ta::presentation::localization::tr("Use entered text as Item ID"), 230.0f, 180.0f))
                    submit_config_value(context, item_id, entered);
                if (!compact)
                {
                    ImGui::SameLine();
                    ImGui::TextColored(ta::presentation::theme::palette::muted, "%s", ta::presentation::localization::tr("Search index is built from live game item templates.").c_str());
                }
                else
                {
                    ta::presentation::widgets::hint_text("Search index is built from live game item templates.");
                }
            }

            ImGui::PushTextWrapPos(0.0f);
            ImGui::TextColored(ta::presentation::theme::palette::muted,
                               "%s: %zu   %s: %zu   %s: %zu   %s: %s",
                               ta::presentation::localization::tr("Visible").c_str(), model.visible_indices().size(),
                               ta::presentation::localization::tr("Wishlist").c_str(), model.wishlist_count(),
                               ta::presentation::localization::tr("Catalog").c_str(), snapshot.static_catalog_size,
                               ta::presentation::localization::tr("Raid Status").c_str(),
                               ta::presentation::localization::tr(context.in_raid ? "IN RAID" : "OUT OF RAID").c_str());
            ImGui::PopTextWrapPos();
        }

        void draw_catalog_table(const ItemSnapshot& snapshot,
                                const std::vector<std::size_t>& visible_indices,
                                const ConfigValueSnapshot& item_id,
                                const ItemsPageContext& context,
                                const std::string& current_id)
        {
            if (snapshot.items.empty() && !snapshot.ready)
            {
                ta::presentation::widgets::empty_state(
                    "Waiting for game item data",
                    "Enter a raid to load the item catalog from the game.");
                return;
            }

            if (snapshot.loading)
                ta::presentation::widgets::hint_text("Loading item templates in small batches...");

            if (visible_indices.empty())
            {
                ta::presentation::widgets::empty_state(
                    "No matching items",
                    "Try another item name, category, or Item ID.");
                return;
            }

            if (!ImGui::BeginTable("##item_catalog_table", 2,
                                   ImGuiTableFlags_ScrollY |
                                   ImGuiTableFlags_RowBg |
                                   ImGuiTableFlags_BordersInnerV |
                                   ImGuiTableFlags_Resizable |
                                   ImGuiTableFlags_SizingStretchProp,
                                   ImGui::GetContentRegionAvail()))
            {
                return;
            }

            ImGui::TableSetupScrollFreeze(0, 1);
            ImGui::TableSetupColumn(ta::presentation::localization::tr("Name").c_str(), ImGuiTableColumnFlags_WidthStretch, 0.65f);
            ImGui::TableSetupColumn(ta::presentation::localization::tr("Category").c_str(), ImGuiTableColumnFlags_WidthStretch, 0.35f);
            ImGui::TableHeadersRow();

            ImGuiListClipper clipper;
            clipper.Begin(static_cast<int>(visible_indices.size()));
            while (clipper.Step())
            {
                for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; ++row)
                {
                    const ItemEntry& item = snapshot.items[visible_indices[static_cast<std::size_t>(row)]];
                    ImGui::PushID(item.id.c_str());
                    ImGui::TableNextRow();
                    if (item.wishlisted)
                    {
                        const ImU32 wishlist_row = ImGui::GetColorU32(
                            ta::presentation::theme::with_alpha(ta::presentation::theme::palette::accent2, 0.16f));
                        ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, wishlist_row);
                        ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1, wishlist_row);
                    }
                    ImGui::TableSetColumnIndex(0);
                    const bool selected = item.id == current_id;
                    if (ImGui::Selectable((item.name + "##select").c_str(), selected,
                                          ImGuiSelectableFlags_SpanAllColumns))
                    {
                        submit_config_value(context, item_id, item.id);
                    }
                    if (ImGui::IsItemHovered())
                        ImGui::SetTooltip("%s", item.id.c_str());
                    ImGui::TableSetColumnIndex(1);
                    ImGui::TextDisabled("%s", ta::presentation::localization::tr(std::string(
                        ta::features::items::contracts::item_category_label_key(item.category))).c_str());
                    ImGui::PopID();
                }
            }
            ImGui::EndTable();
        }

        void draw_selected_item(const ItemSnapshot& snapshot, const std::string& current_id)
        {
            const ItemEntry* selected = ItemCatalogModel::find_by_id(snapshot, current_id);
            ImGui::TextColored(ta::presentation::theme::palette::accent, "%s", ta::presentation::localization::tr("Selected Item").c_str());
            if (selected)
            {
                ImGui::TextWrapped("%s", selected->name.c_str());
                ImGui::TextColored(ta::presentation::theme::palette::muted, "%s", ta::presentation::localization::tr(std::string(
                    ta::features::items::contracts::item_category_label_key(selected->category))).c_str());
                if (selected->wishlisted)
                {
                    ImGui::SameLine();
                    ImGui::TextColored(ta::presentation::theme::palette::accent2, "• %s", ta::presentation::localization::tr("Wishlist").c_str());
                }
                ImGui::TextDisabled("%s", selected->id.c_str());
            }
            else if (!current_id.empty())
            {
                ImGui::TextUnformatted(ta::presentation::localization::tr("Manual or uncatalogued item").c_str());
                ImGui::TextDisabled("%s", current_id.c_str());
            }
            else
            {
                ImGui::TextUnformatted(ta::presentation::localization::tr("No item selected").c_str());
            }
        }

        void draw_item_action(const ItemsPageContext& context,
                              const ta::features::items::contracts::PendingAction action,
                              const char* label,
                              const float width)
        {
            const char* key = ActionFeedbackPresenter::item_action_key(action);
            const bool pending = ActionFeedbackPresenter::is_pending(key);
            ImGui::BeginDisabled(!context.in_raid || pending);
            const std::string button_label = pending
                ? ta::presentation::localization::tr("Queued") + "...##" + key
                : ta::presentation::localization::tr(label) + "##" + key;
            if (ta::presentation::widgets::action_button(button_label, width, width * 0.72f))
                request_item_action(context, action);
            ImGui::EndDisabled();
        }

        void draw_item_builder(const ItemsPageContext& context,
                               const ItemSnapshot& snapshot,
                               const ConfigPanelSnapshot& panel)
        {
            const ConfigValueSnapshot* item_id = find_value(&panel, "item_id");
            const ConfigValueSnapshot* amount = find_value(&panel, "amount");
            const ConfigValueSnapshot* override_max = find_value(&panel, "override_max_amount");
            const ConfigValueSnapshot* found_in_raid = find_value(&panel, "fir");
            const ConfigValueSnapshot* item_slot = find_value(&panel, "item_slot");
            const ConfigValueSnapshot* overwrite_slot = find_value(&panel, "overwrite_slot");
            const ConfigValueSnapshot* no_slot_limits = find_value(&panel, "no_slot_limits");
            const ConfigValueSnapshot* increased_transfer_size = find_value(&panel, "increased_transfer_size");
            if (!item_id)
                return;

            const std::string current_id = trim(item_id->text_value);
            draw_selected_item(snapshot, current_id);
            ImGui::Separator();

            ImGui::Spacing();
            if (amount)
                ta::presentation::widgets::draw_config_value(*amount, context.submit_config);
            if (override_max)
                ta::presentation::widgets::draw_config_value(*override_max, context.submit_config);
            if (found_in_raid)
                ta::presentation::widgets::draw_config_value(*found_in_raid, context.submit_config);
            const ItemEntry* selected = ItemCatalogModel::find_by_id(snapshot, current_id);
            if (selected && amount && (!override_max || !override_max->bool_value))
            {
                const int max_stack = (std::max)(1, selected->max_stack_size);
                const int requested = (std::max)(1, amount->int_value);
                const int stack_count = (requested + max_stack - 1) / max_stack;
                if (stack_count > 1)
                {
                    ImGui::TextColored(ta::presentation::theme::palette::muted, "%s: %d × %d",
                                       ta::presentation::localization::tr("Generated stacks").c_str(),
                                       stack_count, max_stack);
                }
            }

            ImGui::Spacing();
            if (item_slot)
                ta::presentation::widgets::draw_config_value(*item_slot, context.submit_config);
            const bool quest_inventory = item_slot &&
                item_slot->int_value == ta::features::items::contracts::quest_item_inventory_slot_index;
            if (overwrite_slot)
                ta::presentation::widgets::draw_config_value_disabled(*overwrite_slot, context.submit_config, quest_inventory);
            if (quest_inventory)
                ta::presentation::widgets::hint_text("Created items will be placed in the quest item inventory.");
            else if (overwrite_slot && overwrite_slot->bool_value)
                ta::presentation::widgets::warning_text("Overwrite Slot replaces the item currently assigned to the selected equipment slot.");

            ImGui::Spacing();
            if (no_slot_limits)
                ta::presentation::widgets::draw_config_value(*no_slot_limits, context.submit_config);
            if (increased_transfer_size)
                ta::presentation::widgets::draw_config_value(*increased_transfer_size, context.submit_config);
            ta::presentation::widgets::hint_text("These options affect inventory compatibility checks globally.");

            ImGui::Spacing();
            ImGui::BeginDisabled(!context.in_raid || current_id.empty());
            if (ImGui::BeginTable("##item_creation_actions", 2,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextColumn();
                draw_item_action(context, ta::features::items::contracts::PendingAction::CreateItem, "Create Item", 150.0f);
                ImGui::TableNextColumn();
                draw_item_action(context, ta::features::items::contracts::PendingAction::TransitItem, "Transit Item (2-3h)", 175.0f);
                ImGui::EndTable();
            }
            ImGui::EndDisabled();

        }
    }

    void draw_items_page(const MenuContext& ctx, UiState& state)
    {
        const ConfigPanelSnapshot* item_panel = find_item_panel(ctx);
        const ConfigValueSnapshot* item_id = find_value(item_panel, "item_id");
        const ItemSnapshot empty_snapshot{};
        const std::shared_ptr<const ItemSnapshot> catalog = ctx.items.catalog;
        const ItemSnapshot& snapshot = catalog ? *catalog : empty_snapshot;
        const std::string current_id = item_id ? trim(item_id->text_value) : std::string{};

        state.items.refresh(catalog);

        ImGui::BeginChild("##items_workspace", ImGui::GetContentRegionAvail(), false);
        if (!item_panel || !item_id)
        {
            ta::presentation::widgets::empty_state("Item module unavailable");
            ImGui::EndChild();
            return;
        }

        draw_workspace_toolbar(ctx.items, state.items, snapshot, *item_id);
        ImGui::Separator();
        ImGui::Spacing();

        const float scale = ta::presentation::runtime::scale_factor();
        const float gap = ta::presentation::theme::ui_metrics().spacing_md;
        const float available = ImGui::GetContentRegionAvail().x;
        const float height = ImGui::GetContentRegionAvail().y;
        const bool compact = available < 930.0f * scale;

        if (compact)
        {
            const float builder_height = (std::min)(310.0f * scale, height * 0.42f);
            ImGui::BeginChild("##item_builder", ImVec2(0.0f, builder_height), true);
            ta::presentation::widgets::section_header(ta::presentation::localization::tr("Item Builder"));
            draw_item_builder(ctx.items, snapshot, *item_panel);
            ImGui::EndChild();
            ImGui::Spacing();
            ImGui::BeginChild("##catalog_workspace", ImVec2(0.0f, 0.0f), true);
            ta::presentation::widgets::section_header(ta::presentation::localization::tr("Item Catalog"));
            draw_catalog_table(snapshot, state.items.visible_indices(), *item_id, ctx.items, current_id);
            ImGui::EndChild();
        }
        else
        {
            const float builder_width = (std::clamp)(available * 0.34f, 330.0f * scale, 460.0f * scale);
            const float catalog_width = available - builder_width - gap;
            ImGui::BeginChild("##catalog_workspace", ImVec2(catalog_width, height), true);
            ta::presentation::widgets::section_header(ta::presentation::localization::tr("Item Catalog"));
            draw_catalog_table(snapshot, state.items.visible_indices(), *item_id, ctx.items, current_id);
            ImGui::EndChild();

            ImGui::SameLine(0.0f, gap);
            ImGui::BeginChild("##item_builder", ImVec2(builder_width, height), true);
            ta::presentation::widgets::section_header(ta::presentation::localization::tr("Item Builder"));
            draw_item_builder(ctx.items, snapshot, *item_panel);
            ImGui::EndChild();
        }

        ImGui::EndChild();
    }
}
