#include "presentation/pages/ConfigPage.h"

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

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

#include "presentation/localization/UiLocalizationService.h"
#include "presentation/theme/MenuTheme.h"
#include "presentation/action_feedback/ActionFeedbackPresenter.h"
#include "presentation/widgets/BasicWidgets.h"
#include "presentation/widgets/ConfigWidgets.h"
#include "presentation/config/ConfigSnapshotLookup.h"
#include "foundation/text/StringUtils.h"
#include "features/esp/contracts/EspTypes.h"

namespace ta::presentation::pages
{
    namespace
    {

        ta::presentation::pages::PageId map_config_page(const ta::application::config::ConfigCategory category)
        {
            switch (category)
            {
            case ta::application::config::ConfigCategory::Aimbot: return ta::presentation::pages::PageId::Settings;
            case ta::application::config::ConfigCategory::Visuals: return ta::presentation::pages::PageId::Visuals;
            case ta::application::config::ConfigCategory::Exploit: return ta::presentation::pages::PageId::Raid;
            case ta::application::config::ConfigCategory::QuestList: return ta::presentation::pages::PageId::Quests;
            case ta::application::config::ConfigCategory::ItemList: return ta::presentation::pages::PageId::Items;
            case ta::application::config::ConfigCategory::Config:
            default: return ta::presentation::pages::PageId::Settings;
            }
        }

        const ConfigPanelSnapshot* find_panel(const ConfigUiSnapshot* snapshot, const char* id)
        {
            if (!snapshot)
                return nullptr;
            if (snapshot->global_config.id == id)
                return &snapshot->global_config;
            const auto found = std::find_if(snapshot->panels.begin(), snapshot->panels.end(), [id](const ConfigPanelSnapshot& panel)
            {
                return panel.id == id;
            });
            return found == snapshot->panels.end() ? nullptr : &*found;
        }

        std::vector<const ConfigPanelSnapshot*> select_panels(const ConfigUiSnapshot* snapshot, const ta::presentation::pages::PageId page)
        {
            std::vector<const ConfigPanelSnapshot*> selected;
            if (!snapshot)
                return selected;
            selected.reserve(snapshot->panels.size() + 1);
            for (const ConfigPanelSnapshot& panel : snapshot->panels)
            {
                if (map_config_page(panel.category) == page)
                    selected.push_back(&panel);
            }
            return selected;
        }

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

        void draw_value(const ConfigPanelSnapshot* panel,
                        const ConfigCommandSubmitter& submit,
                        const char* id,
                        const bool disabled = false)
        {
            if (const ConfigValueSnapshot* value = find_value(panel, id))
                ta::presentation::widgets::draw_config_value_disabled(*value, submit, disabled);
        }

        void submit_bool_value(const ConfigCommandSubmitter& submit,
                               const ConfigValueSnapshot& value,
                               const bool enabled)
        {
            if (submit && value.valid())
                submit({ConfigCommandType::SetValue, value.key, enabled});
        }

        void submit_int_value(const ConfigCommandSubmitter& submit,
                              const ConfigValueSnapshot* value,
                              const int number)
        {
            if (submit && value && value->valid())
                submit({ConfigCommandType::SetValue, value->key, number});
        }

        void submit_float_value(const ConfigCommandSubmitter& submit,
                                const ConfigValueSnapshot* value,
                                const float number)
        {
            if (submit && value && value->valid())
                submit({ConfigCommandType::SetValue, value->key, number});
        }

        void draw_inline_help(const char* text_key)
        {
            if (!text_key || !*text_key)
                return;

            ImGui::SameLine();
            ImGui::TextDisabled("(?)");
            if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
            {
                ImGui::BeginTooltip();
                ImGui::PushTextWrapPos(ImGui::GetFontSize() * 28.0f);
                ImGui::TextUnformatted(ta::presentation::localization::tr(text_key).c_str());
                ImGui::PopTextWrapPos();
                ImGui::EndTooltip();
            }
        }

        void draw_esp_advanced_value(const ConfigPanelSnapshot* panel,
                                     const ConfigCommandSubmitter& submit,
                                     const char* id,
                                     const char* help_key)
        {
            draw_value(panel, submit, id);
            draw_inline_help(help_key);
        }

        void reset_esp_advanced_settings(const ConfigPanelSnapshot* panel,
                                         const ConfigCommandSubmitter& submit)
        {
            const ta::features::esp::EspAdvancedSettings defaults{};
            submit_int_value(submit, find_value(panel, "local_position_interval_ms"), defaults.local_position_interval_ms);
            submit_int_value(submit, find_value(panel, "player_scan_interval_ms"), defaults.player_scan_interval_ms);
            submit_int_value(submit, find_value(panel, "dynamic_loot_interval_ms"), defaults.dynamic_loot_interval_ms);
            submit_int_value(submit, find_value(panel, "exfil_status_interval_ms"), defaults.exfil_status_interval_ms);
            submit_int_value(submit, find_value(panel, "static_discovery_interval_ms"), defaults.static_discovery_interval_ms);
            submit_int_value(submit, find_value(panel, "wishlist_fallback_interval_ms"), defaults.wishlist_fallback_interval_ms);
            submit_float_value(submit, find_value(panel, "distance_hysteresis_percent"), defaults.distance_hysteresis_percent);
            submit_int_value(submit, find_value(panel, "missing_scans_before_removal"), defaults.missing_scans_before_removal);
            submit_int_value(submit, find_value(panel, "metadata_resolves_per_tick"), defaults.metadata_resolves_per_tick);
            submit_int_value(submit, find_value(panel, "metadata_time_budget_us"), defaults.metadata_time_budget_us);
        }

        void draw_esp_advanced_settings(const ConfigPanelSnapshot* panel,
                                        const ConfigCommandSubmitter& submit)
        {
            if (!panel)
                return;

            ta::presentation::widgets::section_header(
                ta::presentation::localization::tr("Refresh Rates"), false);
            draw_esp_advanced_value(panel, submit, "local_position_interval_ms", "Local Position Refresh Help");
            draw_esp_advanced_value(panel, submit, "player_scan_interval_ms", "Player Scan Help");
            draw_esp_advanced_value(panel, submit, "dynamic_loot_interval_ms", "Dynamic Loot Scan Help");
            draw_esp_advanced_value(panel, submit, "exfil_status_interval_ms", "Exfil Status Refresh Help");
            draw_esp_advanced_value(panel, submit, "static_discovery_interval_ms", "Static Object Scan Help");
            draw_esp_advanced_value(panel, submit, "wishlist_fallback_interval_ms", "Wishlist Fallback Refresh Help");

            ImGui::Spacing();
            ta::presentation::widgets::section_header(
                ta::presentation::localization::tr("Cache Stability"), false);
            draw_esp_advanced_value(panel, submit, "distance_hysteresis_percent", "Distance Hysteresis Help");
            draw_esp_advanced_value(panel, submit, "missing_scans_before_removal", "Missing Scans Before Removal Help");

            ImGui::Spacing();
            ta::presentation::widgets::section_header(
                ta::presentation::localization::tr("Metadata Resolution Budget"), false);
            draw_esp_advanced_value(panel, submit, "metadata_resolves_per_tick", "Metadata Resolves Per Tick Help");
            draw_esp_advanced_value(panel, submit, "metadata_time_budget_us", "Metadata Time Budget Help");

            ImGui::Spacing();
            if (ta::presentation::widgets::action_button(
                    ta::presentation::localization::tr("Restore ESP Advanced Defaults") + "##restore_esp_advanced_defaults",
                    220.0f,
                    160.0f))
            {
                reset_esp_advanced_settings(panel, submit);
            }
        }

        void section_gap()
        {
            ImGui::Spacing();
        }

        void draw_esp_row(const ConfigPanelSnapshot* panel,
                          const ConfigCommandSubmitter& submit,
                          const char* toggle_id,
                          const char* color_id,
                          const char* distance_id = nullptr)
        {
            const ConfigValueSnapshot* toggle = find_value(panel, toggle_id);
            const ConfigValueSnapshot* color = find_value(panel, color_id);
            const ConfigValueSnapshot* distance = distance_id ? find_value(panel, distance_id) : nullptr;
            if (toggle && color)
                ta::presentation::widgets::draw_toggle_color_distance_row(*toggle, *color, distance, submit);
        }

        void draw_visuals_page(const ConfigPanelSnapshot* esp,
                               const ConfigPanelSnapshot* chams,
                               const ConfigCommandSubmitter& submit)
        {
            ImGui::BeginChild("##visuals_page", ImGui::GetContentRegionAvail(), false);

            const auto draw_esp_column = [&]()
            {
                ImGui::PushID("esp_column");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("ESP"));
                if (esp && ImGui::BeginTabBar("##esp_settings_tabs", ImGuiTabBarFlags_FittingPolicyScroll))
                {
                    const std::string general_tab = ta::presentation::localization::tr("General") + "##esp_general_tab";
                    if (ImGui::BeginTabItem(general_tab.c_str()))
                    {
                        ta::presentation::widgets::section_header(ta::presentation::localization::tr("Characters"), false);
                        draw_esp_row(esp, submit, "pmc", "pmc_color");
                        draw_esp_row(esp, submit, "scav", "scav_color");

                        section_gap();
                        ta::presentation::widgets::section_header(ta::presentation::localization::tr("Navigation"), false);
                        draw_esp_row(esp, submit, "extracts", "extracts_color");
                        draw_esp_row(esp, submit, "transits", "transits_color");

                        section_gap();
                        ta::presentation::widgets::section_header(ta::presentation::localization::tr("Loot"), false);
                        draw_esp_row(esp, submit, "normal_item_esp", "normal_item_color", "normal_item_distance");
                        draw_esp_row(esp, submit, "wishlist_item_esp", "wishlist_item_color", "wishlist_item_distance");
                        draw_esp_row(esp, submit, "quest_item_esp", "quest_item_color", "quest_item_distance");
                        draw_esp_row(esp, submit, "container_esp", "container_color", "container_distance");
                        draw_esp_row(esp, submit, "corpse_esp", "corpse_color", "corpse_distance");
                        draw_value(esp, submit, "loot_min_distance");

                        section_gap();
                        ta::presentation::widgets::section_header(ta::presentation::localization::tr("Display"), false);
                        draw_value(esp, submit, "font_size");
                        ImGui::EndTabItem();
                    }

                    const std::string advanced_tab = ta::presentation::localization::tr("Advanced ESP Settings") + "##esp_advanced_tab";
                    if (ImGui::BeginTabItem(advanced_tab.c_str()))
                    {
                        draw_esp_advanced_settings(esp, submit);
                        ImGui::EndTabItem();
                    }
                    ImGui::EndTabBar();
                }
                ImGui::PopID();
            };

            const auto draw_chams_column = [&]()
            {
                ImGui::PushID("chams_column");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Chams"));
                if (chams)
                {
                    ta::presentation::widgets::section_header(ta::presentation::localization::tr("Character Chams"), false);
                    const ConfigValueSnapshot* npc = find_value(chams, "npc_chams");
                    const ConfigValueSnapshot* gear = find_value(chams, "gear_chams");
                    if (npc) ta::presentation::widgets::draw_config_value(*npc, submit);
                    if (gear) ta::presentation::widgets::draw_config_value(*gear, submit);
                    draw_value(chams, submit, "chams_type");
                    draw_value(chams, submit, "visible_color");
                    draw_value(chams, submit, "invisible_color");

                    section_gap();
                    ta::presentation::widgets::section_header(ta::presentation::localization::tr("Player Chams"), false);
                    draw_value(chams, submit, "player_chams");
                    const ConfigValueSnapshot* weapon = find_value(chams, "weapon_chams");
                    if (weapon) ta::presentation::widgets::draw_config_value(*weapon, submit);
                    draw_value(chams, submit, "weapon_type");
                    draw_value(chams, submit, "weapon_color");
                    draw_value(chams, submit, "include_scope");
                }
                ImGui::PopID();
            };

            const ta::presentation::widgets::TwoColumnLayout layout =
                ta::presentation::widgets::two_column_layout(200.0f);
            if (layout.stacked)
            {
                draw_esp_column();
                ImGui::Spacing();
                draw_chams_column();
            }
            else if (ImGui::BeginTable("##visuals_columns", 2,
                                       ImGuiTableFlags_SizingStretchSame |
                                       ImGuiTableFlags_BordersInnerV |
                                       ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextRow();
                ImGui::TableSetColumnIndex(0);
                draw_esp_column();
                ImGui::TableSetColumnIndex(1);
                draw_chams_column();
                ImGui::EndTable();
            }
            ImGui::EndChild();
        }

        void submit_select(const ConfigCommandSubmitter& submit,
                           const ConfigValueSnapshot& value,
                           const int index)
        {
            if (submit)
                submit({ConfigCommandType::SetValue, value.key, index});
        }

        void draw_searchable_select(const ConfigCommandSubmitter& submit,
                                    const ConfigValueSnapshot& value,
                                    std::string& search)
        {
            if (!value.valid() || value.options.empty())
                return;

            const int selected = (std::clamp)(value.int_value, 0, static_cast<int>(value.options.size()) - 1);
            const std::string preview = ta::presentation::localization::tr(value.options[static_cast<std::size_t>(selected)]);
            const std::string label = ta::presentation::localization::tr(value.label_key) + "##" + value.key;

            if (!ta::presentation::widgets::begin_field_row(label))
                return;

            if (ImGui::BeginCombo("##value", preview.c_str()))
            {
                ImGui::SetNextItemWidth(-1.0f);
                ImGui::InputTextWithHint("##filter", ta::presentation::localization::tr("Search skills").c_str(), &search);
                ImGui::Separator();
                const std::string needle = ta::foundation::text::lower_copy(search);
                for (std::size_t i = 0; i < value.options.size(); ++i)
                {
                    const std::string translated = ta::presentation::localization::tr(value.options[i]);
                    if (!needle.empty() && ta::foundation::text::lower_copy(translated + " " + value.options[i]).find(needle) == std::string::npos)
                        continue;
                    const bool is_selected = static_cast<int>(i) == selected;
                    if (ImGui::Selectable((translated + "##" + std::to_string(i)).c_str(), is_selected))
                        submit_select(submit, value, static_cast<int>(i));
                    if (is_selected)
                        ImGui::SetItemDefaultFocus();
                }
                ImGui::EndCombo();
            }
            ta::presentation::widgets::end_field_row();
        }

        void draw_progression_controls(const ConfigPanelSnapshot* player,
                                       const ConfigCommandSubmitter& submit,
                                       ProgressionPageState& state,
                                       const bool in_raid)
        {
            if (!player)
            {
                ta::presentation::widgets::empty_state("Progression module unavailable");
                return;
            }

            const auto draw_experience = [&]()
            {
                ImGui::PushID("experience_progression");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Experience"));
                draw_value(player, submit, "exp_type");
                draw_value(player, submit, "exp_amount");
                draw_value(player, submit, "add_exp", !in_raid);
                ImGui::PopID();
            };

            const auto draw_fence_reputation = [&]()
            {
                ImGui::PushID("fence_reputation_progression");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Fence Reputation"));
                draw_value(player, submit, "fence_rep_source");
                draw_value(player, submit, "fence_rep_amount");
                draw_value(player, submit, "add_fence_rep", !in_raid);
                ImGui::PopID();
            };

            const auto draw_trader_reputation = [&]()
            {
                ImGui::PushID("trader_reputation_progression");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Trader Reputation"));
                draw_value(player, submit, "trader_select");
                draw_value(player, submit, "trader_rep_amount");
                draw_value(player, submit, "add_trader_rep", !in_raid);
                ImGui::PopID();
            };

            const auto draw_skill = [&]()
            {
                ImGui::PushID("skill_progression");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Skill"));
                if (const ConfigValueSnapshot* skill = find_value(player, "skill_select"))
                    draw_searchable_select(submit, *skill, state.skill_search);
                draw_value(player, submit, "skill_level");
                draw_value(player, submit, "set_skill", !in_raid);
                ImGui::PopID();
            };

            draw_experience();
            ImGui::Spacing();
            draw_fence_reputation();
            ImGui::Spacing();
            draw_trader_reputation();
            ImGui::Spacing();
            draw_skill();
        }

        bool draw_action_value_button(const ConfigValueSnapshot* value,
                                      const ConfigCommandSubmitter& submit,
                                      const char* feature,
                                      const float width,
                                      const bool disabled = false)
        {
            if (!value || !submit || !value->valid())
                return false;

            const bool pending = ActionFeedbackPresenter::is_pending(value->key);
            ImGui::BeginDisabled(disabled || pending);
            const std::string label = pending
                ? ta::presentation::localization::tr("Queued") + "...##" + value->key
                : ta::presentation::localization::tr(value->label_key) + "##" + value->key;
            const bool pressed = ta::presentation::widgets::action_button(label, width, width * 0.70f);
            ImGui::EndDisabled();
            if (!pressed)
                return false;

            ConfigCommand command{ConfigCommandType::InvokeAction, value->key, {}};
            command.trace_id = ActionFeedbackPresenter::begin(
                value->key,
                ta::presentation::localization::tr(value->label_key),
                feature ? feature : "Actions");
            submit(std::move(command));
            return true;
        }

        void draw_toggle_hotkey_row(const ConfigPanelSnapshot* player,
                                    const ConfigCommandSubmitter& submit,
                                    const char* toggle_id,
                                    const char* hotkey_id)
        {
            const ConfigValueSnapshot* toggle = find_value(player, toggle_id);
            const ConfigValueSnapshot* hotkey = find_value(player, hotkey_id);
            ImGui::PushID(toggle_id);
            const int columns = ta::presentation::widgets::compact_layout(200.0f) ? 1 : 2;
            if (ImGui::BeginTable("##toggle_hotkey", columns,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextColumn();
                if (toggle)
                    ta::presentation::widgets::draw_config_value(*toggle, submit);
                ImGui::TableNextColumn();
                if (hotkey)
                    ta::presentation::widgets::draw_config_value(*hotkey, submit);
                ImGui::EndTable();
            }
            ImGui::PopID();
        }

        void draw_hotkey_pair_row(const ConfigPanelSnapshot* player,
                                  const ConfigCommandSubmitter& submit,
                                  const char* left_id,
                                  const char* right_id)
        {
            ImGui::PushID(left_id);
            const int columns = ta::presentation::widgets::compact_layout(200.0f) ? 1 : 2;
            if (ImGui::BeginTable("##hotkey_pair", columns,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextColumn();
                draw_value(player, submit, left_id);
                ImGui::TableNextColumn();
                draw_value(player, submit, right_id);
                ImGui::EndTable();
            }
            ImGui::PopID();
        }

        void draw_survival_controls(const ConfigPanelSnapshot* player,
                                    const ConfigCommandSubmitter& submit)
        {
            constexpr const char* survival_ids[] = {
                "god_mode",
                "infinite_stamina",
                "no_hunger_thirst",
                "always_survive",
                "instant_search",
                "no_malfunction",
                "infinite_ammo"
            };

            constexpr int columns = 2;
            if (ImGui::BeginTable("##survival_controls", columns,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                for (const char* id : survival_ids)
                {
                    ImGui::TableNextColumn();
                    ImGui::PushID(id);
                    draw_value(player, submit, id);
                    ImGui::PopID();
                }
                ImGui::EndTable();
            }
        }

        void draw_movement_controls(const ConfigPanelSnapshot* player,
                                    const ConfigCommandSubmitter& submit)
        {
            draw_toggle_hotkey_row(player, submit, "speed_hack", "speed_hotkey");
            draw_value(player, submit, "speed");
            draw_toggle_hotkey_row(player, submit, "fly_mode", "fly_hotkey");
            draw_hotkey_pair_row(player, submit, "up", "down");
        }

        void draw_world_action_controls(const ConfigPanelSnapshot* world,
                                        const ConfigCommandSubmitter& submit,
                                        const bool in_raid)
        {
            draw_action_value_button(find_value(world, "unlock_doors"), submit, "World", 150.0f, !in_raid);

            ImGui::Spacing();
            ta::presentation::widgets::section_header(ta::presentation::localization::tr("Direct Teleport"), false);
            constexpr int action_columns = 3;
            if (ImGui::BeginTable("##direct_item_teleport_actions", action_columns,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextColumn();
                draw_action_value_button(find_value(world, "teleport_wishlist_items"), submit, "Item Teleport", 120.0f, !in_raid);
                ImGui::TableNextColumn();
                draw_action_value_button(find_value(world, "teleport_quest_items"), submit, "Item Teleport", 120.0f, !in_raid);
                ImGui::TableNextColumn();
                draw_action_value_button(find_value(world, "teleport_corpses"), submit, "Item Teleport", 120.0f, !in_raid);
                ImGui::EndTable();
            }

        }

        void draw_item_teleport_controls(const ConfigPanelSnapshot* world,
                                         const ConfigCommandSubmitter& submit,
                                         const bool in_raid)
        {
            const int settings_columns = ta::presentation::widgets::compact_layout(200.0f) ? 1 : 2;
            if (ImGui::BeginTable("##item_teleport_settings", settings_columns,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextColumn();
                draw_value(world, submit, "item_teleport_circle_radius");
                ImGui::TableNextColumn();
                draw_value(world, submit, "item_teleport_height_offset");
                ImGui::EndTable();
            }

            constexpr const char* normal_category_ids[] = {
                "include_normal_weapons",
                "include_normal_ammo",
                "include_normal_weapon_mods",
                "include_normal_equipment",
                "include_normal_medical",
                "include_normal_diet",
                "include_normal_keys",
                "include_normal_containers",
                "include_normal_trade_goods",
                "include_normal_other"
            };

            ta::presentation::widgets::section_header(ta::presentation::localization::tr("Normal Item Categories"), false);

            bool has_normal_category = false;
            constexpr int category_columns = 3;
            if (ImGui::BeginTable("##normal_item_categories", category_columns,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                for (const char* id : normal_category_ids)
                {
                    const ConfigValueSnapshot* category = find_value(world, id);
                    if (!category)
                        continue;
                    has_normal_category = has_normal_category || category->bool_value;
                    ImGui::TableNextColumn();
                    bool enabled = category->bool_value;
                    const std::string label = ta::presentation::localization::tr(category->label_key) + "##" + category->key;
                    if (ImGui::Checkbox(label.c_str(), &enabled))
                        submit_bool_value(submit, *category, enabled);
                }
                ImGui::EndTable();
            }

            if (ta::presentation::widgets::action_button(
                    ta::presentation::localization::tr("Select all") + "##select_all_normal_categories",
                    92.0f,
                    64.0f))
            {
                for (const char* id : normal_category_ids)
                {
                    if (const ConfigValueSnapshot* category = find_value(world, id))
                        submit_bool_value(submit, *category, true);
                }
            }

            ImGui::SameLine();
            if (ta::presentation::widgets::action_button(
                    ta::presentation::localization::tr("Clear") + "##clear_normal_categories",
                    76.0f,
                    56.0f))
            {
                for (const char* id : normal_category_ids)
                {
                    if (const ConfigValueSnapshot* category = find_value(world, id))
                        submit_bool_value(submit, *category, false);
                }
            }

            ImGui::SameLine();
            ImGui::BeginDisabled(!has_normal_category);
            draw_action_value_button(find_value(world, "teleport_normal_items"), submit, "Item Teleport", 145.0f, !in_raid);
            ImGui::EndDisabled();

            if (!has_normal_category)
            {
                ImGui::SameLine();
                ImGui::TextDisabled("%s", ta::presentation::localization::tr("Select at least one category.").c_str());
            }
        }

        void draw_raid_page(const ConfigPanelSnapshot* player,
                            const ConfigPanelSnapshot* world,
                            const ConfigCommandSubmitter& submit,
                            ProgressionPageState& progression_state,
                            const bool in_raid)
        {
            ImGui::BeginChild("##raid_page", ImGui::GetContentRegionAvail(), false);

            if (ImGui::BeginTable("##raid_columns", 2,
                                  ImGuiTableFlags_SizingStretchSame |
                                  ImGuiTableFlags_BordersInnerV |
                                  ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextRow();

                ImGui::TableSetColumnIndex(0);
                ImGui::PushID("raid_left_column");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Player Status"));
                draw_survival_controls(player, submit);

                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Movement"));
                draw_movement_controls(player, submit);

                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Item Teleport"));
                draw_item_teleport_controls(world, submit, in_raid);

                ta::presentation::widgets::section_header(ta::presentation::localization::tr("World Actions"));
                draw_world_action_controls(world, submit, in_raid);
                ImGui::PopID();

                ImGui::TableSetColumnIndex(1);
                ImGui::PushID("raid_progression_column");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("PROGRESSION"));
                draw_progression_controls(player, submit, progression_state, in_raid);
                ImGui::PopID();

                ImGui::EndTable();
            }

            ImGui::EndChild();
        }

        void draw_config_page(const MenuContext& ctx)
        {
            const ConfigUiSnapshot* snapshot = ctx.config.get();
            const ConfigPanelSnapshot* global = snapshot ? &snapshot->global_config : nullptr;
            const ConfigPanelSnapshot* watermark = find_panel(snapshot, "watermark");

            ImGui::BeginChild("##config_page", ImGui::GetContentRegionAvail(), false);

            const auto draw_general = [&]()
            {
                ImGui::PushID("general_config");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("General"));
                draw_value(global, ctx.submit_config, "language");
                draw_value(global, ctx.submit_config, "menu_key");
                ImGui::PopID();
            };

            const auto draw_watermark = [&]()
            {
                ImGui::PushID("watermark_config");
                ta::presentation::widgets::section_header(ta::presentation::localization::tr("Watermark"));
                if (watermark)
                {
                    const ConfigValueSnapshot* enabled = find_value(watermark, "enabled");
                    if (enabled)
                        ta::presentation::widgets::draw_config_value(*enabled, ctx.submit_config);
                    draw_value(watermark, ctx.submit_config, "text");
                    draw_value(watermark, ctx.submit_config, "color");
                    draw_value(watermark, ctx.submit_config, "font_size");
                }
                else
                {
                    ta::presentation::widgets::empty_state("Watermark module unavailable");
                }
                ImGui::PopID();
            };

            const ta::presentation::widgets::TwoColumnLayout layout =
                ta::presentation::widgets::two_column_layout(200.0f);
            if (layout.stacked)
            {
                draw_general();
                ImGui::Spacing();
                draw_watermark();
            }
            else if (ImGui::BeginTable("##config_columns", 2,
                                       ImGuiTableFlags_SizingStretchSame |
                                       ImGuiTableFlags_BordersInnerV |
                                       ImGuiTableFlags_NoSavedSettings))
            {
                ImGui::TableNextRow();
                ImGui::TableSetColumnIndex(0);
                draw_general();
                ImGui::TableSetColumnIndex(1);
                draw_watermark();
                ImGui::EndTable();
            }

            ImGui::EndChild();
        }
    }


    void draw_raid_config_page(const MenuContext& ctx,
                               ProgressionPageState& progression_state)
    {
        const ConfigUiSnapshot* snapshot = ctx.config.get();
        draw_raid_page(
            find_panel(snapshot, "player"),
            find_panel(snapshot, "world"),
            ctx.submit_config,
            progression_state,
            ctx.in_raid);
    }

    void draw_config_category_page(const MenuContext& ctx,
                                   const ta::presentation::pages::PageId page,
                                   const bool single_column,
                                   const bool include_global_config)
    {
        const ConfigUiSnapshot* snapshot = ctx.config.get();
        if (page == ta::presentation::pages::PageId::Visuals)
        {
            draw_visuals_page(find_panel(snapshot, "esp"), find_panel(snapshot, "chams"), ctx.submit_config);
            return;
        }
        if (page == ta::presentation::pages::PageId::Settings && include_global_config)
        {
            draw_config_page(ctx);
            return;
        }

        std::vector<const ConfigPanelSnapshot*> panels = select_panels(snapshot, page);
        if (include_global_config && snapshot && !snapshot->global_config.values.empty())
            panels.insert(panels.begin(), &snapshot->global_config);

        if (single_column)
            ta::presentation::widgets::draw_config_panels_single_column(panels, ctx.submit_config);
        else
            ta::presentation::widgets::draw_config_panels_two_columns(panels, ctx.submit_config);
    }
}
