#include "Menu.h"
#include "raylib.h"
#include "../Initialization/Initialization.h"
#include "../Backend/Image.h"
#include "../Backend/TokenStore/TokenStore.h"
#include "../Backend/Network/NetworkClient.h"
#include "../Backend/HWID/HWIDCollector.h"
#include "../Backend/JWT/JWTDecoder.h"
#include <thread>

Menu* Menu::Get() {
    static Menu instance;
    return &instance;
}

static GradientStop stops[] = {
    { RLColor{ 0, 185, 255, 255 }, 0.0f },
    { RLColor{ 255, 1, 247, 255 }, 0.5f },
    { RLColor{ 232, 255, 0, 255 }, 1.0f }
};

static RLTexture2D GetBgTexture() {
    static RLTexture2D tex = []() {
        RLImage img = RLLoadImageFromMemory(".png", BgTexture, sizeof(BgTexture));
        RLTexture2D t = RLLoadTextureFromImage(img);
        RLUnloadImage(img);
        return t;
    }();
    return tex;
}

static void BackGround() {
    auto render = Render::Get();
    RLVector2 Win_size = Initialization::Get()->Get_WinSize();

    RLDrawRectangleLinesEx({ 0, 0, Win_size.x, Win_size.y }, 1, RLColor{0, 0, 0, 255});
    RLDrawRectangleLinesEx({ 1, 1, Win_size.x - 2, Win_size.y - 2 }, 1, RLColor{60, 60, 60, 255});
    RLDrawRectangleLinesEx({ 2, 2, Win_size.x - 4, Win_size.y - 4 }, 3, RLColor{40, 40, 40, 255});
    RLDrawRectangleLinesEx({ 5, 5, Win_size.x - 10, Win_size.y - 10 }, 1, RLColor{60, 60, 60, 255});
    RLDrawRectangleLinesEx({ 6, 6, Win_size.x - 12, Win_size.y - 12 }, 1, RLColor{0, 0, 0, 255});

    RLTexture2D bg = GetBgTexture();
    float texW = (float)bg.width;
    float texH = (float)bg.height;
    float areaX = 7, areaY = 7;
    float areaW = Win_size.x - 14, areaH = Win_size.y - 14;

    for (float y = areaY; y < areaY + areaH; y += texH) {
        for (float x = areaX; x < areaX + areaW; x += texW) {
            float drawW = texW;
            float drawH = texH;
            if (x + drawW > areaX + areaW) drawW = areaX + areaW - x;
            if (y + drawH > areaY + areaH) drawH = areaY + areaH - y;
            RLDrawTexturePro(bg,
                { 0, 0, drawW, drawH },
                { x, y, drawW, drawH },
                { 0, 0 }, 0, RLColor{255, 255, 255, 255});
        }
    }

    render->CustomGradientBar(10, 10, Win_size.x - 20, 1, stops, sizeof(stops) / sizeof(GradientStop));
    render->CustomGradientBar(10, 11, Win_size.x - 20, 1, stops, sizeof(stops) / sizeof(GradientStop));
    render->CustomGradientBar(10, 12, Win_size.x - 20, 1, stops, sizeof(stops) / sizeof(GradientStop));
}

// ─── Startup auto-login ──────────────────────────────

static void TryAutoLogin(Menu* menu) {
    printf("[Menu] Checking saved session for auto-login...\n");

    auto session = TokenStore::Get()->Load();
    if (!session.valid) {
        printf("[Menu] No saved session found.\n");
        menu->SetAutoLoginDone(false);
        return;
    }

    printf("[Menu] Found saved session for user: %s\n", session.username.c_str());

    // Collect HWID and try to refresh
    const auto& hwid = HWIDCollector::Get()->Collect();

    auto result = NetworkClient::Get()->RefreshToken(
        session.refreshToken,
        hwid.cpu, hwid.board, hwid.disk, hwid.mac);

    if (result.success) {
        printf("[Menu] Auto-login SUCCESS: %s\n", session.username.c_str());
        auto* login = menu::Login::Get();
        login->SetAutoLoggedIn(result.refreshToken, result.accessToken, session.username);
        // Re-save the rotated refresh token
        TokenStore::Get()->Save(result.refreshToken, session.username);
        menu->SetAutoLoginDone(true);
    } else {
        printf("[Menu] Auto-login FAILED: %s\n", result.errorCode.c_str());
        TokenStore::Get()->Clear();
        menu->SetAutoLoginDone(false);
    }
}

void Menu::Render() {
    auto connect = menu::Connect::Get();
    auto login = menu::Login::Get();
    auto load = menu::Load::Get();
    auto injector = menu::Injector::Get();

    // ── Startup: attempt auto-login once ─────────────
    if (!m_autoLoginChecked) {
        m_autoLoginChecked = true;
        std::thread(TryAutoLogin, this).detach();
    }

    BackGround();

    // ── Menu flow ───────────────────────────────────
    if (m_autoLoginSuccess) {
        // Auto-login succeeded — skip directly to Load
        load->DrawLoadMenu();
    } else if (!connect->IsConnected()) {
        connect->DrawConnectMenu();       // Step 1: Connect to server
    } else if (!login->Get_loggedIn()) {
        login->DrawLoginMenu();           // Step 2: Login
    } else if (!load->Get_injecting()) {
        load->DrawLoadMenu();             // Step 3: Load/Inject
    } else {
        injector->DrawInjectorMenu();     // Step 4: Injecting
    }
}
