#include <nlohmann/json.hpp>
#include <iostream>
#include <map>
#include <vector>
#include <string>

// OpenGL + GLFW + ImGui includes
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>

// Warfactory interfaces
#include <warfactory/IIO.h>

using json = nlohmann::json;

namespace warfactory {

// Forward declare ITaskScheduler (not in core yet)
class ITaskScheduler;

class IModule {
public:
    virtual ~IModule() = default;
    virtual void initialize(const json& config, IIO* io, ITaskScheduler* scheduler) = 0;
    virtual void process(const json& input) = 0;
    virtual void shutdown() = 0;
    virtual json getState() = 0;
    virtual void setState(const json& state) = 0;
    virtual std::string getType() const = 0;
};

/**
 * @brief ClientUI Module with Real Graphics - OpenGL + ImGui Interface
 *
 * Provides real graphical interface to interact with server modules.
 * Uses GLFW for windowing and ImGui for UI rendering.
 * Hot-reloadable for rapid UI development.
 */
class ClientUIModuleGraphical : public IModule {
private:
    IIO* io = nullptr;
    ITaskScheduler* taskScheduler = nullptr;
    bool initialized = false;

    // Graphics context
    GLFWwindow* window = nullptr;
    bool window_should_close = false;

    // UI State
    struct UIState {
        bool show_main_window = true;
        bool show_economy_window = false;
        bool show_macroentity_window = false;
        bool show_globalmap_window = false;
        bool show_demo_window = false;

        // Data from server modules
        json economy_data;
        json macroentity_data;
        json globalmap_data;

        // GlobalMap viewer state
        int map_view_chunk_x = 0;
        int map_view_chunk_y = 0;
        float map_zoom = 1.0f;
        int selected_tile_x = -1;
        int selected_tile_y = -1;
        json selected_tile_data;

        // UI logs
        std::vector<std::string> log_messages;

        // Window properties
        ImVec2 main_window_pos = ImVec2(50, 50);
        ImVec2 main_window_size = ImVec2(400, 300);
    };

    UIState ui_state;
    int frame_count = 0;

public:
    ClientUIModuleGraphical() {
        std::cout << "🎮 ClientUI Graphical Module created - OpenGL Ready!" << std::endl;
    }

    virtual ~ClientUIModuleGraphical() {
        cleanup();
        std::cout << "🎮 ClientUI Graphical Module destroyed (frames: " << frame_count << ")" << std::endl;
    }

    void initialize(const json& moduleConfig, IIO* ioService, ITaskScheduler* scheduler) override {
        std::cout << "🚀 Initializing ClientUI Graphical module..." << std::endl;

        io = ioService;
        taskScheduler = scheduler;

        // Initialize GLFW
        if (!glfwInit()) {
            std::cerr << "❌ Failed to initialize GLFW" << std::endl;
            return;
        }

        // Configure GLFW
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

        // Create window
        window = glfwCreateWindow(800, 600, "Warfactory Client - Hot Reload Ready!", nullptr, nullptr);
        if (!window) {
            std::cerr << "❌ Failed to create GLFW window" << std::endl;
            glfwTerminate();
            return;
        }

        glfwMakeContextCurrent(window);
        glfwSwapInterval(1); // Enable vsync

        // Initialize ImGui
        IMGUI_CHECKVERSION();
        ImGui::CreateContext();
        ImGuiIO& imgio = ImGui::GetIO();
        imgio.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;

        // Setup ImGui style
        ImGui::StyleColorsDark();

        // 🚀 Performance optimizations for high resolution
        ImGuiIO& io_imgui = ImGui::GetIO();
        io_imgui.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;  // Don't change mouse cursor
        io_imgui.ConfigInputTextCursorBlink = false;  // No blinking cursor
        io_imgui.ConfigDragClickToInputText = false;  // Disable some interactions

        // Get window size for DPI scaling
        int fb_width, fb_height;
        glfwGetFramebufferSize(window, &fb_width, &fb_height);

        // Reduce global font scale for high DPI (renders fewer pixels)
        if (fb_width > 2000) {  // 2K/4K screens
            io_imgui.FontGlobalScale = 0.85f;  // Smaller UI = fewer pixels to draw
        }

        // Setup Platform/Renderer backends
        ImGui_ImplGlfw_InitForOpenGL(window, true);
        ImGui_ImplOpenGL3_Init("#version 330 core");

        // Initialize UI state
        ui_state.log_messages.push_back("GraphicsUI initialized with OpenGL");

        // Subscribe to server module responses via IntraIO
        if (io) {
            io->subscribe("economy:response");
            io->subscribe("macroentity:response");
            io->subscribe("globalmap:response");
            ui_state.log_messages.push_back("✅ Subscribed to server responses via IntraIO");
            std::cout << "📡 Subscribed to economy, macroentity and globalmap responses" << std::endl;
        } else {
            ui_state.log_messages.push_back("❌ No IO service - running in simulation mode");
        }

        initialized = true;
        std::cout << "✅ ClientUI Graphical module initialized" << std::endl;
    }

    void process(const json& input) override {
        if (!initialized || !window) return;

        // Check if window should close
        if (glfwWindowShouldClose(window)) {
            window_should_close = true;
            return;
        }

        frame_count++;

        // Poll events
        glfwPollEvents();

        // Start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        // Process incoming messages from server modules
        processServerMessages();

        // Render UI windows
        renderMainWindow();

        // Render Economy only when needed
        if (ui_state.show_economy_window) {
            renderEconomyWindow();
        }

        if (ui_state.show_macroentity_window) {
            renderMacroEntityWindow();
        }

        // Render GlobalMap only when needed
        if (ui_state.show_globalmap_window) {
            renderGlobalMapWindow();
        }

        if (ui_state.show_demo_window) {
            ImGui::ShowDemoWindow(&ui_state.show_demo_window);
        }

        // Handle input events
        if (!input.empty()) {
            std::string type = input.value("type", "");
            if (type == "server_response") {
                handleServerResponse(input);
            }
        }

        // Rendering
        ImGui::Render();

        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);

        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        glfwSwapBuffers(window);
    }

    void shutdown() override {
        std::cout << "🛑 Shutting down ClientUI Graphical module" << std::endl;
        cleanup();
        initialized = false;
    }

    json getState() override {
        return {
            {"frame_count", frame_count},
            {"window_open", window != nullptr && !window_should_close},
            {"windows_state", {
                {"main_window", ui_state.show_main_window},
                {"economy_window", ui_state.show_economy_window},
                {"macroentity_window", ui_state.show_macroentity_window},
                {"demo_window", ui_state.show_demo_window}
            }},
            {"window_pos", {ui_state.main_window_pos.x, ui_state.main_window_pos.y}},
            {"window_size", {ui_state.main_window_size.x, ui_state.main_window_size.y}},
            {"log_count", ui_state.log_messages.size()},
            {"initialized", initialized}
        };
    }

    void setState(const json& state) override {
        std::cout << "🔄 Restoring ClientUI Graphical state (hot-reload)" << std::endl;

        if (state.contains("frame_count")) {
            frame_count = state["frame_count"];
        }

        if (state.contains("windows_state")) {
            auto windows = state["windows_state"];
            ui_state.show_main_window = windows.value("main_window", true);
            ui_state.show_economy_window = windows.value("economy_window", false);
            ui_state.show_macroentity_window = windows.value("macroentity_window", false);
            ui_state.show_demo_window = windows.value("demo_window", false);
        }

        if (state.contains("window_pos") && state["window_pos"].is_array() && state["window_pos"].size() == 2) {
            ui_state.main_window_pos.x = state["window_pos"][0];
            ui_state.main_window_pos.y = state["window_pos"][1];
        }

        if (state.contains("window_size") && state["window_size"].is_array() && state["window_size"].size() == 2) {
            ui_state.main_window_size.x = state["window_size"][0];
            ui_state.main_window_size.y = state["window_size"][1];
        }

        ui_state.log_messages.push_back("Graphics state restored via hot-reload");

        std::cout << "✅ ClientUI Graphical state restored: frame " << frame_count << std::endl;
    }

    std::string getType() const override {
        return "client-ui-graphical";
    }

    bool shouldClose() const {
        return window_should_close;
    }

private:
    void cleanup() {
        if (initialized) {
            ImGui_ImplOpenGL3_Shutdown();
            ImGui_ImplGlfw_Shutdown();
            ImGui::DestroyContext();
        }

        if (window) {
            glfwDestroyWindow(window);
            window = nullptr;
        }

        glfwTerminate();
    }

    void processServerMessages() {
        // REAL IMPLEMENTATION: Pull messages from IntraIO
        if (io) {
            while (io->hasMessages() > 0) {
                auto message = io->pullMessage();
                std::string topic = message.topic;
                json data = message.data;

                ui_state.log_messages.push_back("📨 Received: " + topic);

                // Keep only last 25 messages for performance
                if (ui_state.log_messages.size() > 25) {
                    ui_state.log_messages.erase(ui_state.log_messages.begin());
                }

                // Route based on topic
                if (topic == "economy:response") {
                    ui_state.economy_data = data.value("data", json{});
                    ui_state.log_messages.push_back("💰 Economy data updated via IntraIO");
                }
                else if (topic == "macroentity:response") {
                    ui_state.macroentity_data = data.value("data", json{});
                    ui_state.log_messages.push_back("🏢 MacroEntity data updated via IntraIO");
                }
                else if (topic == "globalmap:response") {
                    ui_state.globalmap_data = data;
                    ui_state.log_messages.push_back("🗺️ GlobalMap data updated via IntraIO");
                }

                // Keep log manageable
                if (ui_state.log_messages.size() > 20) {
                    ui_state.log_messages.erase(ui_state.log_messages.begin());
                }
            }
        } else {
            // Fallback simulation every few frames
            if (frame_count % 300 == 0) { // Every 5 seconds at 60fps
                ui_state.log_messages.push_back("Frame " + std::to_string(frame_count) + " - Simulation mode");

                if (ui_state.log_messages.size() > 20) {
                    ui_state.log_messages.erase(ui_state.log_messages.begin());
                }
            }
        }
    }

    void renderMainWindow() {
        ImGui::SetNextWindowPos(ui_state.main_window_pos, ImGuiCond_FirstUseEver);
        ImGui::SetNextWindowSize(ui_state.main_window_size, ImGuiCond_FirstUseEver);

        ImGui::Begin("🚀 Warfactory Client - Hot Reload Ready!", &ui_state.show_main_window);

        ImGui::Text("🎮 Client Status: Online");
        ImGui::Text("⚡ Frame: %d", frame_count);
        ImGui::Text("🔗 Server Modules: Economy, MacroEntity");

        ImGui::Separator();

        if (ImGui::Button("💰 Get Economy Prices")) {
            requestEconomyPrices();
        }

        ImGui::SameLine();
        if (ImGui::Button("🏢 Get Companies")) {
            requestCompanies();
        }

        ImGui::Separator();

        if (ImGui::Button("📊 Economy Window")) {
            ui_state.show_economy_window = !ui_state.show_economy_window;
        }

        ImGui::SameLine();
        if (ImGui::Button("🏭 MacroEntity Window")) {
            ui_state.show_macroentity_window = !ui_state.show_macroentity_window;
        }

        ImGui::SameLine();
        if (ImGui::Button("🗺️ Global Map")) {
            ui_state.show_globalmap_window = !ui_state.show_globalmap_window;
            // Request initial map data when opening
            if (ui_state.show_globalmap_window) {
                requestGlobalMapChunk(ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);
            }
        }

        ImGui::SameLine();
        if (ImGui::Button("🔧 ImGui Demo")) {
            ui_state.show_demo_window = !ui_state.show_demo_window;
        }

        ImGui::Separator();

        // Display recent messages
        ImGui::Text("📜 Recent Messages:");
        ImGui::BeginChild("Messages", ImVec2(0, 100), true);
        for (const auto& msg : ui_state.log_messages) {
            ImGui::Text("• %s", msg.c_str());
        }
        ImGui::EndChild();

        // Update window state
        ui_state.main_window_pos = ImGui::GetWindowPos();
        ui_state.main_window_size = ImGui::GetWindowSize();

        ImGui::End();
    }

    void renderEconomyWindow() {
        ImGui::Begin("💰 Economy Data", &ui_state.show_economy_window);

        ImGui::Text("📊 Market Prices:");
        ImGui::Separator();

        if (!ui_state.economy_data.empty()) {
            if (ui_state.economy_data.contains("steel_plate")) {
                ImGui::Text("🔧 Steel Plate: %.2f€", ui_state.economy_data["steel_plate"].get<double>());
            }
            if (ui_state.economy_data.contains("iron_ore")) {
                ImGui::Text("⛏️ Iron Ore: %.2f€", ui_state.economy_data["iron_ore"].get<double>());
            }
            if (ui_state.economy_data.contains("copper_wire")) {
                ImGui::Text("🔌 Copper Wire: %.2f€", ui_state.economy_data["copper_wire"].get<double>());
            }
            if (ui_state.economy_data.contains("coal")) {
                ImGui::Text("⚫ Coal: %.2f€", ui_state.economy_data["coal"].get<double>());
            }
        } else {
            ImGui::Text("No economy data available");
            ImGui::Text("Click 'Get Economy Prices' to fetch data");
        }

        ImGui::Separator();
        if (ImGui::Button("🔄 Refresh Prices")) {
            requestEconomyPrices();
        }

        ImGui::End();
    }

    void renderMacroEntityWindow() {
        ImGui::Begin("🏢 Companies & States", &ui_state.show_macroentity_window);

        ImGui::Text("🏭 Active Companies:");
        ImGui::Separator();

        if (!ui_state.macroentity_data.empty()) {
            for (const auto& [company_id, company_data] : ui_state.macroentity_data.items()) {
                if (company_data.is_object()) {
                    ImGui::Text("🏢 %s", company_id.c_str());
                    if (company_data.contains("cash")) {
                        ImGui::Text("   💰 Cash: %.0f€", company_data["cash"].get<double>());
                    }
                    if (company_data.contains("strategy")) {
                        ImGui::Text("   📋 Strategy: %s", company_data["strategy"].get<std::string>().c_str());
                    }
                    ImGui::Separator();
                }
            }
        } else {
            ImGui::Text("No company data available");
            ImGui::Text("Click 'Get Companies' to fetch data");
        }

        if (ImGui::Button("🔄 Refresh Companies")) {
            requestCompanies();
        }

        ImGui::End();
    }

    void handleServerResponse(const json& response) {
        std::string source = response.value("source", "unknown");

        if (source == "economy") {
            ui_state.economy_data = response.value("data", json{});
            ui_state.log_messages.push_back("💰 Economy data updated");
        }
        else if (source == "macroentity") {
            ui_state.macroentity_data = response.value("data", json{});
            ui_state.log_messages.push_back("🏢 MacroEntity data updated");
        }
    }

    void requestEconomyPrices() {
        ui_state.log_messages.push_back("📤 Requesting economy prices...");

        // REAL IMPLEMENTATION: Use IntraIO to request economy data
        if (io) {
            json request = {{"type", "get_prices"}};
            io->publish("economy:request", request);
            ui_state.log_messages.push_back("✅ Economy request sent via IntraIO");
        } else {
            ui_state.log_messages.push_back("❌ No IO service available");
            // Fallback simulation
            ui_state.economy_data = {
                {"steel_plate", 5.2 + (frame_count % 100) * 0.01},
                {"iron_ore", 1.1 + (frame_count % 50) * 0.002},
                {"copper_wire", 2.0 + (frame_count % 75) * 0.005},
                {"coal", 0.8 + (frame_count % 30) * 0.001}
            };
        }
    }

    void requestCompanies() {
        ui_state.log_messages.push_back("📤 Requesting companies data...");

        // REAL IMPLEMENTATION: Use IntraIO to request company data
        if (io) {
            json request = {{"type", "get_companies"}};
            io->publish("macroentity:request", request);
            ui_state.log_messages.push_back("✅ MacroEntity request sent via IntraIO");
        } else {
            ui_state.log_messages.push_back("❌ No IO service available");

            // For testing, simulate the response
            ui_state.macroentity_data = {
                {"SteelCorp", {{"cash", 2500000 + frame_count * 100}, {"strategy", "aggressive"}}},
                {"IronWorks", {{"cash", 1800000 + frame_count * 50}, {"strategy", "conservative"}}},
                {"LogisticsLtd", {{"cash", 1200000 + frame_count * 75}, {"strategy", "opportunistic"}}}
            };
        }
    }

    void requestGlobalMapChunk(int chunk_x, int chunk_y) {
        ui_state.log_messages.push_back("📤 Requesting GlobalMap chunk (" + std::to_string(chunk_x) + ", " + std::to_string(chunk_y) + ")");

        if (io) {
            json request = {
                {"type", "get_chunk"},
                {"chunk_x", chunk_x},
                {"chunk_y", chunk_y}
            };
            io->publish("globalmap:request", request);
            ui_state.log_messages.push_back("✅ GlobalMap request sent via IntraIO");
        } else {
            ui_state.log_messages.push_back("❌ No IO service available");
        }
    }

    void renderGlobalMapWindow() {
        ImGui::Begin("🗺️ Global Map Viewer", &ui_state.show_globalmap_window, ImGuiWindowFlags_NoScrollbar);

        // Navigation controls
        ImGui::Text("🧭 Navigation");
        ImGui::Separator();

        // Chunk coordinates
        ImGui::Text("Current Chunk: (%d, %d)", ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);

        if (ImGui::Button("⬅️")) {
            ui_state.map_view_chunk_x--;
            requestGlobalMapChunk(ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);
        }
        ImGui::SameLine();
        if (ImGui::Button("⬆️")) {
            ui_state.map_view_chunk_y--;
            requestGlobalMapChunk(ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);
        }
        ImGui::SameLine();
        if (ImGui::Button("⬇️")) {
            ui_state.map_view_chunk_y++;
            requestGlobalMapChunk(ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);
        }
        ImGui::SameLine();
        if (ImGui::Button("➡️")) {
            ui_state.map_view_chunk_x++;
            requestGlobalMapChunk(ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);
        }

        ImGui::SameLine();
        if (ImGui::Button("🔄 Refresh")) {
            requestGlobalMapChunk(ui_state.map_view_chunk_x, ui_state.map_view_chunk_y);
        }

        ImGui::Separator();

        // Map display
        if (ui_state.globalmap_data.contains("chunk")) {
            auto chunk_data = ui_state.globalmap_data["chunk"];

            ImGui::Text("🗺️ Chunk (%d, %d) - 64x64 tiles",
                       chunk_data.value("chunk_x", 0),
                       chunk_data.value("chunk_y", 0));

            // Simple grid display (8x8 for now to keep it manageable)
            ImGui::BeginChild("MapGrid", ImVec2(0, 300), true);

            if (chunk_data.contains("tiles")) {
                auto tiles = chunk_data["tiles"];

                // Display tiles in an 8x8 grid (sample every 8 tiles from the 64x64 chunk)
                for (int grid_y = 0; grid_y < 8; grid_y++) {
                    for (int grid_x = 0; grid_x < 8; grid_x++) {
                        // Sample tile from the 64x64 chunk
                        int tile_x = grid_x * 8;
                        int tile_y = grid_y * 8;

                        if (tile_y < tiles.size() && tile_x < tiles[tile_y].size()) {
                            auto tile = tiles[tile_y][tile_x];
                            std::string feature = tile.value("feature", "empty");

                            // Color-code by feature
                            ImVec4 color = getFeatureColor(feature);

                            ImGui::PushStyleColor(ImGuiCol_Button, color);

                            std::string button_id = "##" + std::to_string(grid_x) + "_" + std::to_string(grid_y);
                            if (ImGui::Button(getFeatureIcon(feature).c_str(), ImVec2(32, 32))) {
                                // Tile clicked - show details
                                ui_state.selected_tile_x = ui_state.map_view_chunk_x * 64 + tile_x;
                                ui_state.selected_tile_y = ui_state.map_view_chunk_y * 64 + tile_y;
                                ui_state.selected_tile_data = tile;
                            }

                            ImGui::PopStyleColor();

                            if (grid_x < 7) ImGui::SameLine();
                        }
                    }
                }
            }

            ImGui::EndChild();

            // Selected tile details
            if (ui_state.selected_tile_x >= 0) {
                ImGui::Separator();
                ImGui::Text("🎯 Selected Tile (%d, %d)", ui_state.selected_tile_x, ui_state.selected_tile_y);

                if (!ui_state.selected_tile_data.empty()) {
                    std::string feature = ui_state.selected_tile_data.value("feature", "unknown");
                    int resource_amount = ui_state.selected_tile_data.value("resource_amount", 0);
                    double strategic_value = ui_state.selected_tile_data.value("strategic_value", 0.0);

                    ImGui::Text("🏷️ Feature: %s %s", getFeatureIcon(feature).c_str(), feature.c_str());
                    if (resource_amount > 0) {
                        ImGui::Text("💎 Resources: %d", resource_amount);
                    }
                    ImGui::Text("⭐ Strategic Value: %.1f", strategic_value);
                }
            }

        } else {
            ImGui::Text("No map data loaded");
            ImGui::Text("Click 'Refresh' to load current chunk");
        }

        ImGui::End();
    }

    ImVec4 getFeatureColor(const std::string& feature) {
        if (feature == "iron_ore") return ImVec4(0.6f, 0.3f, 0.1f, 1.0f);      // Brown
        if (feature == "copper_ore") return ImVec4(0.8f, 0.4f, 0.1f, 1.0f);    // Orange
        if (feature == "coal") return ImVec4(0.1f, 0.1f, 0.1f, 1.0f);          // Black
        if (feature == "oil") return ImVec4(0.2f, 0.2f, 0.2f, 1.0f);           // Dark gray
        if (feature == "city") return ImVec4(0.7f, 0.7f, 0.7f, 1.0f);          // Light gray
        if (feature == "forest") return ImVec4(0.1f, 0.5f, 0.1f, 1.0f);        // Green
        if (feature == "mountain") return ImVec4(0.4f, 0.4f, 0.4f, 1.0f);      // Gray
        if (feature == "river") return ImVec4(0.1f, 0.3f, 0.8f, 1.0f);         // Blue
        if (feature == "desert") return ImVec4(0.8f, 0.7f, 0.3f, 1.0f);        // Yellow
        if (feature == "plains") return ImVec4(0.4f, 0.7f, 0.2f, 1.0f);        // Light green
        return ImVec4(0.3f, 0.3f, 0.3f, 1.0f);                                // Default gray
    }

    std::string getFeatureIcon(const std::string& feature) {
        if (feature == "iron_ore") return "⛏️";
        if (feature == "copper_ore") return "🔸";
        if (feature == "coal") return "⚫";
        if (feature == "oil") return "🛢️";
        if (feature == "city") return "🏙️";
        if (feature == "forest") return "🌲";
        if (feature == "mountain") return "⛰️";
        if (feature == "river") return "🌊";
        if (feature == "desert") return "🏜️";
        if (feature == "plains") return "🌾";
        return "⬜";
    }
};

} // namespace warfactory

// C-style export functions for dynamic loading
extern "C" {
    warfactory::IModule* create_module() {
        return new warfactory::ClientUIModuleGraphical();
    }

    void destroy_module(warfactory::IModule* module) {
        delete module;
    }

    const char* get_module_type() {
        return "client-ui-graphical";
    }

    const char* get_module_version() {
        return "1.0.0-opengl";
    }
}