// LevelSelectorState.cpp - Level selection popup state implementation
#include "LevelSelectorState.h"
#include "State.h"
#include "../core/state/StateManager.h"
#include "../core/GlobalState.h"
#include "../graphics/ui/Font.h"
#include <SDL3/SDL.h>
#include <algorithm>
#include <cstdio>
#include <string>
#include "../graphics/renderers/UIRenderer.h"

// Use dynamic logical dimensions from GlobalState instead of hardcoded values

// --- Minimal draw helpers and look-and-feel adapted from the sample ---
static inline SDL_Color RGBA(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255) { return SDL_Color{r, g, b, a}; }

// Palette
static const SDL_Color COL_BG       = {11, 15, 20, 255};
static const SDL_Color COL_PANEL    = {20, 40, 60, 255};
static const SDL_Color COL_PANEL_IN = {26, 46, 66, 255};
static const SDL_Color COL_CYAN     = {0, 255, 255, 200};
static const SDL_Color COL_CYAN_SO  = {0, 255, 255, 32};
static const SDL_Color COL_TILE     = {30, 40, 60, 255};
static const SDL_Color COL_TILE_H   = {60, 80, 100, 255};
static const SDL_Color COL_TILE_B   = {74, 94, 118, 220};
static const SDL_Color COL_NUM      = {233, 241, 255, 255};
static const SDL_Color COL_ACCENT   = {255, 140, 40, 255};
static const SDL_Color COL_TITLE    = {255, 200, 50, 255};
static const SDL_Color COL_FOOTER   = {154, 167, 178, 255};

static void FillRect(SDL_Renderer* r, SDL_FRect rc, SDL_Color c) {
    SDL_SetRenderDrawBlendMode(r, SDL_BLENDMODE_BLEND);
    SDL_SetRenderDrawColor(r, c.r, c.g, c.b, c.a);
    SDL_RenderFillRect(r, &rc);
}
static void StrokeRect(SDL_Renderer* r, SDL_FRect rc, SDL_Color c) {
    SDL_SetRenderDrawBlendMode(r, SDL_BLENDMODE_BLEND);
    SDL_SetRenderDrawColor(r, c.r, c.g, c.b, c.a);
    SDL_RenderRect(r, &rc);
}
static void Line(SDL_Renderer* r, float x1, float y1, float x2, float y2, SDL_Color c) {
    SDL_SetRenderDrawBlendMode(r, SDL_BLENDMODE_BLEND);
    SDL_SetRenderDrawColor(r, c.r, c.g, c.b, c.a);
    SDL_RenderLine(r, x1, y1, x2, y2);
}

// Bitmap-like digits for cell numbers (keeps consistent look without relying on font inside cells)
static void DrawDigit(SDL_Renderer* r, int num, float cx, float cy) {
    SDL_SetRenderDrawColor(r, COL_NUM.r, COL_NUM.g, COL_NUM.b, COL_NUM.a);
    auto glyph = [&](int d, float ox) {
        static const int map[10][15] = {
            {1,1,1, 1,0,1, 1,0,1, 1,0,1, 1,1,1},
            {0,1,0, 1,1,0, 0,1,0, 0,1,0, 1,1,1},
            {1,1,1, 0,0,1, 1,1,1, 1,0,0, 1,1,1},
            {1,1,1, 0,0,1, 0,1,1, 0,0,1, 1,1,1},
            {1,0,1, 1,0,1, 1,1,1, 0,0,1, 0,0,1},
            {1,1,1, 1,0,0, 1,1,1, 0,0,1, 1,1,1},
            {1,1,1, 1,0,0, 1,1,1, 1,0,1, 1,1,1},
            {1,1,1, 0,0,1, 0,1,0, 0,1,0, 0,1,0},
            {1,1,1, 1,0,1, 1,1,1, 1,0,1, 1,1,1},
            {1,1,1, 1,0,1, 1,1,1, 0,0,1, 1,1,1}
        };
        float s = 5.f; float gx = cx + ox - 6.f, gy = cy - 12.f;
        for (int y = 0; y < 5; y++) for (int x = 0; x < 3; x++)
            if (map[d][y * 3 + x]) {
                SDL_FRect p{gx + x * s, gy + y * s, s - 1.f, s - 1.f};
                SDL_RenderFillRect(r, &p);
            }
    };
    if (num < 10) glyph(num, 0);
    else { glyph(num / 10, -8); glyph(num % 10, 8); }
}

// Centered text using project Font, with optional shadow
static void DrawText(SDL_Renderer* r, FontAtlas* font, const std::string& s,
                     float x, float y, float scale, SDL_Color col,
                     bool center = true, bool shadow = true) {
    if (!font) return;
    int w = 0, h = 0; font->measure(s, scale, w, h);
    float tx = x, ty = y;
    if (center) tx -= (float)w / 2.0f;
    if (shadow) {
        font->draw(r, tx + 2.0f, ty + 2.0f, s, scale, {0, 0, 0, 200});
    }
    font->draw(r, tx, ty, s, scale, col);
}

static void Vignette(SDL_Renderer* r, int w, int h) {
    int pad = w / 10;
    FillRect(r, SDL_FRect{0, 0, (float)w, (float)pad}, SDL_Color{0, 0, 0, 140});
    FillRect(r, SDL_FRect{0, (float)h - pad, (float)w, (float)pad}, SDL_Color{0, 0, 0, 140});
    FillRect(r, SDL_FRect{0, 0, (float)pad, (float)h}, SDL_Color{0, 0, 0, 140});
    FillRect(r, SDL_FRect{(float)w - pad, 0, (float)pad, (float)h}, SDL_Color{0, 0, 0, 140});
}

// DrawPanel removed, replaced by UIRenderer::drawSciFiPanel

struct Grid {
    int cols = 4, rows = 5;
    float cellW = 0.f, cellH = 0.f, gapX = 12.f, gapY = 12.f;
    SDL_FRect area{0, 0, 0, 0};
    SDL_FRect cell(int i) const {
        int r = i / cols, c = i % cols;
        return SDL_FRect{ area.x + c * (cellW + gapX), area.y + r * (cellH + gapY), cellW, cellH };
    }
};

static Grid MakeGrid(const SDL_FRect& panel) {
    Grid g;
    float marginX = 34, marginY = 76;
    g.area = SDL_FRect{ panel.x + marginX, panel.y + marginY, panel.w - 2 * marginX, panel.h - marginY - 28 };
    g.cellW = (g.area.w - (g.cols - 1) * g.gapX) / g.cols;
    g.cellH = (g.area.h - (g.rows - 1) * g.gapY) / g.rows;
    return g;
}

static void DrawCell(SDL_Renderer* r, SDL_FRect rc, int idx, bool hovered, bool selected) {
    FillRect(r, rc, selected ? COL_ACCENT : (hovered ? COL_TILE_H : COL_TILE));
    StrokeRect(r, rc, COL_TILE_B);
    Line(r, rc.x + 2, rc.y + 2, rc.x + rc.w - 2, rc.y + 2, SDL_Color{255, 255, 255, 18});
    Line(r, rc.x + 2, rc.y + rc.h - 2, rc.x + rc.w - 2, rc.y + rc.h - 2, SDL_Color{0, 0, 0, 40});
    DrawDigit(r, idx, rc.x + rc.w / 2.f, rc.y + rc.h / 2.f);
}

static int HitTest(const Grid& g, int mx, int my) {
    for (int i = 0; i < 20; i++) {
        SDL_FRect rc = g.cell(i);
        if (mx >= rc.x && mx < rc.x + rc.w && my >= rc.y && my < rc.y + rc.h) return i;
    }
    return -1;
}

LevelSelectorState::LevelSelectorState(StateContext& ctx) : State(ctx) {
}

void LevelSelectorState::onEnter() {
    hoveredLevel = ctx.startLevelSelection ? *ctx.startLevelSelection : 0;
}

void LevelSelectorState::onExit() {
    hoveredLevel = -1;
}

void LevelSelectorState::handleEvent(const SDL_Event& e) {
    if (e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
        // Arrow key navigation (clamped within grid like the sample)
        int c = hoveredLevel < 0 ? 0 : hoveredLevel;
        switch (e.key.scancode) {
            case SDL_SCANCODE_LEFT:  if (c % 4 > 0) c--; break;
            case SDL_SCANCODE_RIGHT: if (c % 4 < 3) c++; break;
            case SDL_SCANCODE_UP:    if (c / 4 > 0) c -= 4; break;
            case SDL_SCANCODE_DOWN:  if (c / 4 < 4) c += 4; break;
            case SDL_SCANCODE_RETURN:
            case SDL_SCANCODE_KP_ENTER:
                selectLevel(hoveredLevel < 0 ? 0 : hoveredLevel);
                return;
            case SDL_SCANCODE_ESCAPE:
                closePopup();
                return;
            default: break;
        }
        hoveredLevel = c;
        if (ctx.startLevelSelection) *ctx.startLevelSelection = hoveredLevel;
    } else if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
        if (e.button.button == SDL_BUTTON_LEFT) {
            // Get dynamic logical dimensions
            const int LOGICAL_W = GlobalState::instance().getLogicalWidth();
            const int LOGICAL_H = GlobalState::instance().getLogicalHeight();
            
            // convert mouse to logical coords (viewport is already centered)
            float lx = (float(e.button.x) - float(lastLogicalVP.x)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
            float ly = (float(e.button.y) - float(lastLogicalVP.y)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
            
            // Use same panel calculation as render (centered)
            const float LOGICAL_W_F = 1200.f;
            const float LOGICAL_H_F = 1000.f;
            float winW = (float)lastLogicalVP.w;
            float winH = (float)lastLogicalVP.h;
            float contentOffsetX = 0.0f;
            float contentOffsetY = 0.0f;
            UIRenderer::computeContentOffsets(winW, winH, LOGICAL_W_F, LOGICAL_H_F, lastLogicalScale, contentOffsetX, contentOffsetY);

            float PW = std::min(520.f, LOGICAL_W_F * 0.65f);
            float PH = std::min(360.f, LOGICAL_H_F * 0.7f);
            SDL_FRect panel{ (LOGICAL_W_F - PW) / 2.f + contentOffsetX, (LOGICAL_H_F - PH) / 2.f - 40.f + contentOffsetY, PW, PH };
            Grid g = MakeGrid(panel);
            int hit = HitTest(g, int(lx), int(ly));
            if (hit != -1) {
                selectLevel(hit);
            } else {
                closePopup();
            }
        }
    } else if (e.type == SDL_EVENT_MOUSE_MOTION) {
    // Get dynamic logical dimensions
    const int LOGICAL_W = GlobalState::instance().getLogicalWidth();
    const int LOGICAL_H = GlobalState::instance().getLogicalHeight();
    
    // convert mouse to logical coords (viewport is already centered)
    float lx = (float(e.motion.x) - float(lastLogicalVP.x)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
    float ly = (float(e.motion.y) - float(lastLogicalVP.y)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
    
    // Use same panel calculation as render (centered)
    const float LOGICAL_W_F = 1200.f;
    const float LOGICAL_H_F = 1000.f;
    float winW = (float)lastLogicalVP.w;
    float winH = (float)lastLogicalVP.h;
    float contentOffsetX = 0.0f;
    float contentOffsetY = 0.0f;
    UIRenderer::computeContentOffsets(winW, winH, LOGICAL_W_F, LOGICAL_H_F, lastLogicalScale, contentOffsetX, contentOffsetY);

    float PW = std::min(520.f, LOGICAL_W_F * 0.65f);
    float PH = std::min(360.f, LOGICAL_H_F * 0.7f);
    SDL_FRect panel{ (LOGICAL_W_F - PW) / 2.f + contentOffsetX, (LOGICAL_H_F - PH) / 2.f - 40.f + contentOffsetY, PW, PH };
    Grid g = MakeGrid(panel);
    hoveredLevel = HitTest(g, int(lx), int(ly));
    }
}

void LevelSelectorState::update(double frameMs) {
    // No continuous updates needed for level selector
    (void)frameMs;
}

void LevelSelectorState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logicalVP) {
    // Cache for input conversion
    lastLogicalScale = logicalScale;
    lastLogicalVP = logicalVP;
    drawLevelSelectionPopup(renderer, logicalScale, logicalVP);
}

void LevelSelectorState::drawLevelSelectionPopup(SDL_Renderer* renderer, float logicalScale, SDL_Rect logicalVP) {
    if (!renderer) return;

    // Use fixed logical dimensions to match main.cpp and ensure consistent layout
    const float LOGICAL_W = 1200.f;
    const float LOGICAL_H = 1000.f;
    
    // Compute content offsets (same approach as MenuState for proper centering)
    float winW = (float)logicalVP.w;
    float winH = (float)logicalVP.h;
    float contentOffsetX = 0.0f;
    float contentOffsetY = 0.0f;
    UIRenderer::computeContentOffsets(winW, winH, LOGICAL_W, LOGICAL_H, logicalScale, contentOffsetX, contentOffsetY);

    // Draw the logo at the top (same as MenuState)
    SDL_Texture* logoToUse = ctx.logoSmallTex ? ctx.logoSmallTex : ctx.logoTex;
    int logoW = 0, logoH = 0;
    if (logoToUse == ctx.logoSmallTex && ctx.logoSmallW > 0) {
        logoW = ctx.logoSmallW;
        logoH = ctx.logoSmallH;
    }
    UIRenderer::drawLogo(renderer, logoToUse, LOGICAL_W, LOGICAL_H, contentOffsetX, contentOffsetY, logoW, logoH);

    // Panel and title strip (in logical space) - centered properly with offsets
    float PW = std::min(520.f, LOGICAL_W * 0.65f);
    float PH = std::min(360.f, LOGICAL_H * 0.7f);
    SDL_FRect panel{ (LOGICAL_W - PW) / 2.f + contentOffsetX, (LOGICAL_H - PH) / 2.f - 40.f + contentOffsetY, PW, PH };

    UIRenderer::drawSciFiPanel(renderer, panel);
    
    // Inner face (LevelSelector specific)
    SDL_FRect inner{panel.x + 12, panel.y + 56, panel.w - 24, panel.h - 68};
    FillRect(renderer, inner, COL_PANEL_IN);
    StrokeRect(renderer, inner, SDL_Color{24, 31, 41, 180});

    // Title text - prefer pixelFont for a blocky title if available, fallback to regular font
    FontAtlas* titleFont = ctx.pixelFont ? ctx.pixelFont : ctx.font;
    DrawText(renderer, titleFont, "SELECT  STARTING  LEVEL", LOGICAL_W / 2.f + contentOffsetX, panel.y + 20.f, 1.2f, COL_TITLE, true, true);

    // Grid of levels
    Grid g = MakeGrid(panel);
    int selectedLevel = ctx.startLevelSelection ? *ctx.startLevelSelection : 0;
    for (int i = 0; i < 20; i++) {
        SDL_FRect rc = g.cell(i);
        DrawCell(renderer, rc, i, hoveredLevel == i, selectedLevel == i);
    }

    // Footer/instructions - use regular TTF font for readability, centered and lower
    FontAtlas* footerFont = ctx.pixelFont ? ctx.pixelFont : ctx.font;
    DrawText(renderer, footerFont, "CLICK A LEVEL TO SELECT   •   ESC = CANCEL",
             LOGICAL_W / 2.f + contentOffsetX, panel.y + panel.h + 60.f, 1.0f, COL_FOOTER, true, true);
}

bool LevelSelectorState::isMouseInPopup(float mouseX, float mouseY, float& popupX, float& popupY, float& popupW, float& popupH) {
    // Get dynamic logical dimensions
    const int LOGICAL_W = GlobalState::instance().getLogicalWidth();
    const int LOGICAL_H = GlobalState::instance().getLogicalHeight();
    
    // Simplified: viewport is already centered, just convert mouse to logical coords
    (void)mouseX; (void)mouseY;
    float lx = 0.f, ly = 0.f;
    if (lastLogicalScale > 0.0f) {
        lx = (float(mouseX) - float(lastLogicalVP.x)) / lastLogicalScale;
        ly = (float(mouseY) - float(lastLogicalVP.y)) / lastLogicalScale;
    }
    const float LOGICAL_W_F = 1200.f;
    const float LOGICAL_H_F = 1000.f;
    float winW = (float)lastLogicalVP.w;
    float winH = (float)lastLogicalVP.h;
    float contentOffsetX = 0.0f;
    float contentOffsetY = 0.0f;
    UIRenderer::computeContentOffsets(winW, winH, LOGICAL_W_F, LOGICAL_H_F, lastLogicalScale, contentOffsetX, contentOffsetY);

    float PW = std::min(520.f, LOGICAL_W_F * 0.65f);
    float PH = std::min(360.f, LOGICAL_H_F * 0.7f);
    SDL_FRect p{ (LOGICAL_W_F - PW) / 2.f + contentOffsetX, (LOGICAL_H_F - PH) / 2.f - 40.f + contentOffsetY, PW, PH };
    popupX = p.x; popupY = p.y; popupW = p.w; popupH = p.h;
    return lx >= popupX && lx <= popupX + popupW && ly >= popupY && ly <= popupY + popupH;
}

int LevelSelectorState::getLevelFromMouse(float mouseX, float mouseY, float popupX, float popupY, float popupW, float popupH) {
    // Get dynamic logical dimensions
    const int LOGICAL_W = GlobalState::instance().getLogicalWidth();
    const int LOGICAL_H = GlobalState::instance().getLogicalHeight();
    
    (void)popupX; (void)popupY; (void)popupW; (void)popupH;
    float lx = 0.f, ly = 0.f;
    if (lastLogicalScale > 0.0f) {
        lx = (float(mouseX) - float(lastLogicalVP.x)) / lastLogicalScale;
        ly = (float(mouseY) - float(lastLogicalVP.y)) / lastLogicalScale;
    }
    const float LOGICAL_W_F = 1200.f;
    const float LOGICAL_H_F = 1000.f;
    float winW = (float)lastLogicalVP.w;
    float winH = (float)lastLogicalVP.h;
    float contentOffsetX = 0.0f;
    float contentOffsetY = 0.0f;
    UIRenderer::computeContentOffsets(winW, winH, LOGICAL_W_F, LOGICAL_H_F, lastLogicalScale, contentOffsetX, contentOffsetY);

    float PW = std::min(520.f, LOGICAL_W_F * 0.65f);
    float PH = std::min(360.f, LOGICAL_H_F * 0.7f);
    SDL_FRect p{ (LOGICAL_W_F - PW) / 2.f + contentOffsetX, (LOGICAL_H_F - PH) / 2.f - 40.f + contentOffsetY, PW, PH };
    Grid g = MakeGrid(p);
    return HitTest(g, (int)lx, (int)ly);
}

void LevelSelectorState::updateHoverFromMouse(float mouseX, float mouseY) {
    hoveredLevel = getLevelFromMouse(mouseX, mouseY, 0, 0, 0, 0);
}

void LevelSelectorState::selectLevel(int level) {
    if (ctx.startLevelSelection) {
        *ctx.startLevelSelection = level;
    }
    // Transition back to menu
    if (ctx.requestFadeTransition) {
        ctx.requestFadeTransition(AppState::Menu);
    } else if (ctx.stateManager) {
        ctx.stateManager->setState(AppState::Menu);
    }
}

void LevelSelectorState::closePopup() {
    // Transition back to menu without changing level
    if (ctx.requestFadeTransition) {
        ctx.requestFadeTransition(AppState::Menu);
    } else if (ctx.stateManager) {
        ctx.stateManager->setState(AppState::Menu);
    }
}
