#include "OptionsState.h"
#include "../core/state/StateManager.h"
#include "../graphics/ui/Font.h"
#include "../audio/Audio.h"
#include "../audio/AudioManager.h"
#include "../audio/SoundEffect.h"
#include <SDL3/SDL.h>
#include <algorithm>
#include <cctype>
#include "../core/Settings.h"
#include "../graphics/renderers/UIRenderer.h"

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

void OptionsState::onEnter() {
    m_selectedField = Field::Fullscreen;
    m_cursorTimer = 0.0;
    m_cursorVisible = true;
    if (SDL_Window* focusWin = SDL_GetKeyboardFocus()) {
        SDL_StartTextInput(focusWin);
    }
}

void OptionsState::onExit() {
    if (SDL_Window* focusWin = SDL_GetKeyboardFocus()) {
        SDL_StopTextInput(focusWin);
    }
}

void OptionsState::handleEvent(const SDL_Event& e) {
    if (e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
        switch (e.key.scancode) {
            case SDL_SCANCODE_ESCAPE:
                exitToMenu();
                return;
            case SDL_SCANCODE_UP:
            case SDL_SCANCODE_W:
                moveSelection(-1);
                return;
            case SDL_SCANCODE_DOWN:
            case SDL_SCANCODE_S:
                moveSelection(1);
                return;
            case SDL_SCANCODE_RETURN:
            case SDL_SCANCODE_KP_ENTER:
            case SDL_SCANCODE_SPACE:
                activateSelection();
                return;
            case SDL_SCANCODE_F:
                toggleFullscreen();
                return;
            case SDL_SCANCODE_LEFT:
            case SDL_SCANCODE_RIGHT:
                if (m_selectedField == Field::Fullscreen) {
                    toggleFullscreen();
                    return;
                }
                if (m_selectedField == Field::Music) {
                    toggleMusic();
                    return;
                }
                if (m_selectedField == Field::SoundFx) {
                    toggleSoundFx();
                    return;
                }
                if (m_selectedField == Field::SmoothScroll) {
                    toggleSmoothScroll();
                    return;
                }
                break;
            default:
                break;
        }

    }
}

void OptionsState::update(double frameMs) {
    m_cursorTimer += frameMs;
    if (m_cursorTimer >= 450.0) {
        m_cursorTimer = 0.0;
        m_cursorVisible = !m_cursorVisible;
    }
}

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

    const float LOGICAL_W = 1200.0f;
    const float LOGICAL_H = 1000.0f;

    float winW = static_cast<float>(logicalVP.w);
    float winH = static_cast<float>(logicalVP.h);
    float contentOffsetX = 0.0f;
    float contentOffsetY = 0.0f;
    UIRenderer::computeContentOffsets(winW, winH, LOGICAL_W, LOGICAL_H, logicalScale, contentOffsetX, contentOffsetY);

    SDL_Texture* logoTexture = ctx.logoSmallTex ? ctx.logoSmallTex : ctx.logoTex;
    int logoW = 0, logoH = 0;
    if (logoTexture == ctx.logoSmallTex && ctx.logoSmallW > 0) {
        logoW = ctx.logoSmallW;
        logoH = ctx.logoSmallH;
    }
    UIRenderer::drawLogo(renderer, logoTexture, LOGICAL_W, LOGICAL_H, contentOffsetX, contentOffsetY, logoW, logoH);

    const float panelW = 520.0f;
    const float panelH = 420.0f;
    SDL_FRect panel{
        (LOGICAL_W - panelW) * 0.5f + contentOffsetX,
        (LOGICAL_H - panelH) * 0.5f + contentOffsetY,
        panelW,
        panelH
    };

    UIRenderer::drawSciFiPanel(renderer, panel);

    // For options/settings we prefer the secondary (Exo2) font for longer descriptions.
    FontAtlas* retroFont = ctx.font ? ctx.font : ctx.pixelFont;

    if (!logoTexture && retroFont) {
        retroFont->draw(renderer, panel.x + 24.0f, panel.y + 24.0f, "OPTIONS", 2.0f, {255, 230, 120, 255});
    }

    SDL_FRect inner{panel.x + 20.0f, panel.y + 80.0f, panel.w - 40.0f, panel.h - 120.0f};
    SDL_SetRenderDrawColor(renderer, 16, 24, 40, 235);
    SDL_RenderFillRect(renderer, &inner);
    SDL_SetRenderDrawColor(renderer, 40, 80, 140, 240);
    SDL_RenderRect(renderer, &inner);

    constexpr int rowCount = 5;
    const float rowHeight = 60.0f;
    const float spacing = std::max(0.0f, (inner.h - rowHeight * rowCount) / (rowCount + 1));

    auto drawField = [&](Field field, float y, const std::string& label, const std::string& value) {
        bool selected = (field == m_selectedField);
        SDL_FRect row{inner.x + 12.0f, y, inner.w - 24.0f, rowHeight};

        SDL_SetRenderDrawColor(renderer, selected ? 55 : 28, selected ? 90 : 40, selected ? 140 : 60, 235);
        SDL_RenderFillRect(renderer, &row);
        SDL_SetRenderDrawColor(renderer, selected ? 180 : 90, selected ? 210 : 120, 255, 255);
        SDL_RenderRect(renderer, &row);

        if (retroFont) {
            SDL_Color labelColor = selected ? SDL_Color{255, 220, 120, 255} : SDL_Color{210, 200, 190, 255};
            SDL_Color valueColor = selected ? SDL_Color{255, 255, 255, 255} : SDL_Color{215, 230, 250, 255};

            if (!label.empty()) {
                float labelScale = 1.2f;
                int labelW = 0;
                int labelH = 0;
                retroFont->measure(label, labelScale, labelW, labelH);
                float labelY = row.y + (row.h - static_cast<float>(labelH)) * 0.5f;
                retroFont->draw(renderer, row.x + 16.0f, labelY, label, labelScale, labelColor);
            }

            int valueW = 0, valueH = 0;
            float valueScale = (field == Field::Back) ? 1.3f : 1.5f;
            retroFont->measure(value, valueScale, valueW, valueH);
            bool rightAlign = (field == Field::Fullscreen || field == Field::Music || field == Field::SoundFx || field == Field::SmoothScroll);
            float valX = rightAlign
                ? (row.x + row.w - static_cast<float>(valueW) - 16.0f)
                : (row.x + (row.w - static_cast<float>(valueW)) * 0.5f);
            float valY = row.y + (row.h - valueH) * 0.5f;
            retroFont->draw(renderer, valX, valY, value, valueScale, valueColor);
        }
    };

    float rowY = inner.y + spacing;

    drawField(Field::Fullscreen, rowY, "FULLSCREEN", isFullscreen() ? "ON" : "OFF");
    rowY += rowHeight + spacing;
    drawField(Field::Music, rowY, "MUSIC", isMusicEnabled() ? "ON" : "OFF");
    rowY += rowHeight + spacing;
    drawField(Field::SoundFx, rowY, "SOUND FX", isSoundFxEnabled() ? "ON" : "OFF");
    rowY += rowHeight + spacing;
    drawField(Field::SmoothScroll, rowY, "SMOOTH SCROLL", isSmoothScrollEnabled() ? "ON" : "OFF");
    rowY += rowHeight + spacing;
    drawField(Field::Back, rowY, "", "RETURN TO MENU");

    (void)retroFont; // footer removed for cleaner layout
}

void OptionsState::moveSelection(int delta) {
    int idx = static_cast<int>(m_selectedField);
    int total = static_cast<int>(Field::Back) + 1;
    idx = (idx + delta + total) % total;
    m_selectedField = static_cast<Field>(idx);
}

void OptionsState::activateSelection() {
    switch (m_selectedField) {
        case Field::Fullscreen:
            toggleFullscreen();
            break;
        case Field::Music:
            toggleMusic();
            break;
        case Field::SoundFx:
            toggleSoundFx();
            break;
        case Field::SmoothScroll:
            toggleSmoothScroll();
            break;
        case Field::Back:
            exitToMenu();
            break;
    }
}

void OptionsState::toggleFullscreen() {
    bool nextState = !isFullscreen();
    if (ctx.applyFullscreen) {
        ctx.applyFullscreen(nextState);
    }
    if (ctx.fullscreenFlag) {
        *ctx.fullscreenFlag = nextState;
    }
    // Save setting
    Settings::instance().setFullscreen(nextState);
    Settings::instance().save();
}

void OptionsState::toggleMusic() {
    if (auto sys = AudioManager::get()) sys->toggleMute();
    // If muted, music is disabled. If not muted, music is enabled.
    // Note: Audio::instance().isMuted() returns true if muted.
    // But Audio class doesn't expose isMuted directly in header usually?
    // Let's assume toggleMute toggles internal state.
    // We can track it via ctx.musicEnabled if it's synced.
    
    bool enabled = true;
    if (ctx.musicEnabled) {
        *ctx.musicEnabled = !*ctx.musicEnabled;
        enabled = *ctx.musicEnabled;
    }
    
    // Save setting
    Settings::instance().setMusicEnabled(enabled);
    Settings::instance().save();
}

void OptionsState::toggleSoundFx() {
    bool next = !SoundEffectManager::instance().isEnabled();
    SoundEffectManager::instance().setEnabled(next);
    // Save setting
    Settings::instance().setSoundEnabled(next);
    Settings::instance().save();
}

void OptionsState::toggleSmoothScroll() {
    bool next = !Settings::instance().isSmoothScrollEnabled();
    Settings::instance().setSmoothScrollEnabled(next);
    Settings::instance().save();
}

void OptionsState::exitToMenu() {
    // Try a graceful fade transition if available, but always ensure we
    // return to the Menu state so the UI is responsive to the user's action.
    if (ctx.requestFadeTransition) {
        ctx.requestFadeTransition(AppState::Menu);
    }
    if (ctx.stateManager) {
        ctx.stateManager->setState(AppState::Menu);
    }
}

bool OptionsState::isFullscreen() const {
    if (ctx.queryFullscreen) {
        return ctx.queryFullscreen();
    }
    return ctx.fullscreenFlag ? *ctx.fullscreenFlag : false;
}

bool OptionsState::isMusicEnabled() const {
    if (ctx.musicEnabled) {
        return *ctx.musicEnabled;
    }
    return true;
}

bool OptionsState::isSoundFxEnabled() const {
    return SoundEffectManager::instance().isEnabled();
}

bool OptionsState::isSmoothScrollEnabled() const {
    return Settings::instance().isSmoothScrollEnabled();
}
