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

using json = nlohmann::json;

namespace warfactory {

// Forward declare interfaces
class IIO;
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 Simulated Graphics - Console-based "GUI"
 *
 * Simulates a graphical interface using console output and input.
 * Shows what the real OpenGL version would do without requiring graphics drivers.
 * Perfect for testing UI logic and hot-reload in server environments.
 */
class ClientUIModuleSimulatedGL : public IModule {
private:
    IIO* io = nullptr;
    ITaskScheduler* taskScheduler = nullptr;
    bool initialized = false;
    bool running = false;

    // Simulated window state
    struct WindowState {
        bool show_main_window = true;
        bool show_economy_window = false;
        bool show_macroentity_window = false;
        bool show_demo_window = false;

        // Window "positions" (simulated)
        struct {int x = 100, y = 50;} main_pos;
        struct {int x = 300, y = 200;} economy_pos;
        struct {int x = 500, y = 300;} macroentity_pos;

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

        // UI event queue (simulated)
        std::vector<std::string> ui_events;
        std::vector<std::string> log_messages;
    };

    WindowState window_state;
    int frame_count = 0;
    std::chrono::steady_clock::time_point last_render;

public:
    ClientUIModuleSimulatedGL() {
        std::cout << "🎮 ClientUI Simulated Graphics Module created - Console GUI Ready!" << std::endl;
        last_render = std::chrono::steady_clock::now();
    }

    virtual ~ClientUIModuleSimulatedGL() {
        std::cout << "🎮 ClientUI Simulated Graphics Module destroyed (frames: " << frame_count << ")" << std::endl;
    }

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

        io = ioService;
        taskScheduler = scheduler;

        std::cout << "🖼️ Creating simulated graphics context..." << std::endl;
        std::cout << "   └─ Window: 800x600 (simulated)" << std::endl;
        std::cout << "   └─ ImGui: Dark theme (simulated)" << std::endl;
        std::cout << "   └─ OpenGL: v3.3 Core (simulated)" << std::endl;

        // Initialize simulated UI state
        window_state.log_messages.push_back("Simulated Graphics UI initialized");
        window_state.log_messages.push_back("Window created: 800x600");
        window_state.log_messages.push_back("ImGui context ready");

        running = true;
        initialized = true;

        std::cout << "✅ ClientUI Simulated Graphics module initialized" << std::endl;
        std::cout << "🎯 Simulation Mode: Console-based interface rendering" << std::endl;
    }

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

        frame_count++;

        // Simulate 60 FPS rendering
        auto now = std::chrono::steady_clock::now();
        auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_render).count();

        if (delta >= 16) { // ~60 FPS
            renderFrame();
            last_render = now;
        }

        // Process server messages
        if (!input.empty()) {
            std::string type = input.value("type", "");
            if (type == "server_response") {
                handleServerResponse(input);
            } else if (type == "ui_command") {
                handleUICommand(input);
            }
        }

        // Simulate user interactions (for demo)
        simulateUserInteractions();
    }

    void shutdown() override {
        std::cout << "🛑 Shutting down ClientUI Simulated Graphics module" << std::endl;
        std::cout << "🖼️ Destroying simulated graphics context..." << std::endl;
        running = false;
        initialized = false;
    }

    json getState() override {
        return {
            {"frame_count", frame_count},
            {"running", running},
            {"windows", {
                {"main_window", window_state.show_main_window},
                {"economy_window", window_state.show_economy_window},
                {"macroentity_window", window_state.show_macroentity_window},
                {"demo_window", window_state.show_demo_window}
            }},
            {"positions", {
                {"main", {window_state.main_pos.x, window_state.main_pos.y}},
                {"economy", {window_state.economy_pos.x, window_state.economy_pos.y}},
                {"macroentity", {window_state.macroentity_pos.x, window_state.macroentity_pos.y}}
            }},
            {"log_count", window_state.log_messages.size()},
            {"initialized", initialized}
        };
    }

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

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

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

        if (state.contains("positions")) {
            auto pos = state["positions"];
            if (pos.contains("main") && pos["main"].is_array() && pos["main"].size() == 2) {
                window_state.main_pos.x = pos["main"][0];
                window_state.main_pos.y = pos["main"][1];
            }
        }

        window_state.log_messages.push_back("Simulated graphics state restored via hot-reload");

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

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

    bool isRunning() const {
        return running;
    }

private:
    void renderFrame() {
        // Simulate frame rendering every 60 frames (1 second)
        if (frame_count % 60 == 0) {
            std::cout << "\n🖼️ === SIMULATED FRAME RENDER === Frame " << frame_count << " ===" << std::endl;

            if (window_state.show_main_window) {
                renderMainWindow();
            }

            if (window_state.show_economy_window) {
                renderEconomyWindow();
            }

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

            std::cout << "🖼️ === END FRAME RENDER ===\n" << std::endl;
        }
    }

    void renderMainWindow() {
        std::cout << "┌─ 🚀 Warfactory Client - Hot Reload Ready! ────────────────┐" << std::endl;
        std::cout << "│ Position: (" << window_state.main_pos.x << ", " << window_state.main_pos.y << ")                                           │" << std::endl;
        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ 🎮 Client Status: Online          ⚡ Frame: " << frame_count << "             │" << std::endl;
        std::cout << "│ 🔗 Server Modules: Economy, MacroEntity                   │" << std::endl;
        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ [💰 Get Economy Prices] [🏢 Get Companies]                 │" << std::endl;
        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ [📊 Economy Window] [🏭 MacroEntity Window] [🔧 Demo]       │" << std::endl;
        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ 📜 Recent Messages:                                        │" << std::endl;

        // Show last 3 log messages
        int shown = 0;
        for (auto it = window_state.log_messages.rbegin(); it != window_state.log_messages.rend() && shown < 3; ++it, ++shown) {
            std::cout << "│ • " << *it;
            // Pad to 56 chars
            for (int i = it->length(); i < 54; i++) std::cout << " ";
            std::cout << "│" << std::endl;
        }

        std::cout << "└────────────────────────────────────────────────────────────┘" << std::endl;
    }

    void renderEconomyWindow() {
        std::cout << "┌─ 💰 Economy Data ─────────────────────────────────────────┐" << std::endl;
        std::cout << "│ Position: (" << window_state.economy_pos.x << ", " << window_state.economy_pos.y << ")                                          │" << std::endl;
        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ 📊 Market Prices:                                          │" << std::endl;

        if (!window_state.economy_data.empty()) {
            if (window_state.economy_data.contains("steel_plate")) {
                printf("│ 🔧 Steel Plate: %.2f€                                      │\n", window_state.economy_data["steel_plate"].get<double>());
            }
            if (window_state.economy_data.contains("iron_ore")) {
                printf("│ ⛏️ Iron Ore: %.2f€                                         │\n", window_state.economy_data["iron_ore"].get<double>());
            }
            if (window_state.economy_data.contains("copper_wire")) {
                printf("│ 🔌 Copper Wire: %.2f€                                      │\n", window_state.economy_data["copper_wire"].get<double>());
            }
        } else {
            std::cout << "│ No economy data available                                  │" << std::endl;
            std::cout << "│ Click 'Get Economy Prices' to fetch data                  │" << std::endl;
        }

        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ [🔄 Refresh Prices]                                        │" << std::endl;
        std::cout << "└────────────────────────────────────────────────────────────┘" << std::endl;
    }

    void renderMacroEntityWindow() {
        std::cout << "┌─ 🏢 Companies & States ──────────────────────────────────┐" << std::endl;
        std::cout << "│ Position: (" << window_state.macroentity_pos.x << ", " << window_state.macroentity_pos.y << ")                                         │" << std::endl;
        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ 🏭 Active Companies:                                        │" << std::endl;

        if (!window_state.macroentity_data.empty()) {
            for (const auto& [company_id, company_data] : window_state.macroentity_data.items()) {
                if (company_data.is_object()) {
                    std::cout << "│ 🏢 " << company_id;
                    for (int i = company_id.length(); i < 50; i++) std::cout << " ";
                    std::cout << "│" << std::endl;

                    if (company_data.contains("cash")) {
                        printf("│    💰 Cash: %.0f€                                      │\n", company_data["cash"].get<double>());
                    }
                    if (company_data.contains("strategy")) {
                        std::cout << "│    📋 Strategy: " << company_data["strategy"].get<std::string>();
                        for (int i = company_data["strategy"].get<std::string>().length(); i < 35; i++) std::cout << " ";
                        std::cout << "│" << std::endl;
                    }
                }
            }
        } else {
            std::cout << "│ No company data available                                  │" << std::endl;
        }

        std::cout << "│                                                            │" << std::endl;
        std::cout << "│ [🔄 Refresh Companies]                                     │" << std::endl;
        std::cout << "└────────────────────────────────────────────────────────────┘" << std::endl;
    }

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

        if (source == "economy") {
            window_state.economy_data = response.value("data", json{});
            window_state.log_messages.push_back("💰 Economy data updated from server");
            std::cout << "📊 [GRAPHICS] Economy data received and cached for rendering" << std::endl;
        }
        else if (source == "macroentity") {
            window_state.macroentity_data = response.value("data", json{});
            window_state.log_messages.push_back("🏢 MacroEntity data updated from server");
            std::cout << "🏭 [GRAPHICS] MacroEntity data received and cached for rendering" << std::endl;
        }

        // Keep log manageable
        if (window_state.log_messages.size() > 10) {
            window_state.log_messages.erase(window_state.log_messages.begin());
        }
    }

    void handleUICommand(const json& command) {
        std::string action = command.value("action", "");

        if (action == "get_economy_prices") {
            requestEconomyPrices();
        } else if (action == "get_companies") {
            requestCompanies();
        } else if (action == "toggle_economy_window") {
            window_state.show_economy_window = !window_state.show_economy_window;
            window_state.log_messages.push_back("📊 Economy window toggled");
        } else if (action == "toggle_macroentity_window") {
            window_state.show_macroentity_window = !window_state.show_macroentity_window;
            window_state.log_messages.push_back("🏢 MacroEntity window toggled");
        }
    }

    void simulateUserInteractions() {
        // Simulate user clicking buttons at intervals
        if (frame_count == 120) { // 2 seconds
            window_state.log_messages.push_back("🖱️ Simulated: User clicked 'Get Economy Prices'");
            requestEconomyPrices();
        }

        if (frame_count == 180) { // 3 seconds
            window_state.show_economy_window = true;
            window_state.log_messages.push_back("🖱️ Simulated: User opened Economy window");
        }

        if (frame_count == 240) { // 4 seconds
            window_state.log_messages.push_back("🖱️ Simulated: User clicked 'Get Companies'");
            requestCompanies();
        }

        if (frame_count == 300) { // 5 seconds
            window_state.show_macroentity_window = true;
            window_state.log_messages.push_back("🖱️ Simulated: User opened MacroEntity window");
        }

        if (frame_count == 600) { // 10 seconds - stop simulation
            running = false;
            window_state.log_messages.push_back("⏰ Simulation completed - would normally keep running");
        }
    }

    void requestEconomyPrices() {
        window_state.log_messages.push_back("📤 Requesting economy prices...");
        std::cout << "📡 [UI] Sending economy price request to server..." << std::endl;

        // In real implementation: io->publish("economy:request", {{"type", "get_prices"}});

        // Simulate server response with dynamic prices
        window_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() {
        window_state.log_messages.push_back("📤 Requesting companies data...");
        std::cout << "📡 [UI] Sending companies request to server..." << std::endl;

        // In real implementation: io->publish("macroentity:request", {{"type", "get_companies"}});

        // Simulate server response with dynamic company data
        window_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"}}}
        };
    }
};

} // namespace warfactory

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

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

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

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