#include "ui_manager.h"

#include <SDL3/SDL.h>
#include <string>

#include "../ball.h"                // for Ball
#include "../defines.h"             // for TEXT_DURATION, NOTIFICATION_DURATION, AppMode, SimulationMode
#include "../engine.h"              // for Engine (info de sistema)
#include "../scene/scene_manager.h" // for SceneManager
#include "../shapes/shape.h"        // for Shape
#include "../text/textrenderer.h"   // for TextRenderer
#include "../theme_manager.h"       // for ThemeManager
#include "notifier.h"               // for Notifier
#include "help_overlay.h"           // for HelpOverlay

UIManager::UIManager()
    : text_renderer_(nullptr)
    , text_renderer_debug_(nullptr)
    , text_renderer_notifier_(nullptr)
    , notifier_(nullptr)
    , help_overlay_(nullptr)
    , show_debug_(false)
    , show_text_(true)
    , text_()
    , text_pos_(0)
    , text_init_time_(0)
    , fps_last_time_(0)
    , fps_frame_count_(0)
    , fps_current_(0)
    , fps_text_("FPS: 0")
    , vsync_text_("VSYNC ON")
    , renderer_(nullptr)
    , theme_manager_(nullptr)
    , physical_window_width_(0)
    , physical_window_height_(0)
    , current_font_size_(18) {  // Tamaño por defecto (medium)
}

UIManager::~UIManager() {
    // Limpieza: Los objetos creados con new deben ser eliminados
    delete text_renderer_;
    delete text_renderer_debug_;
    delete text_renderer_notifier_;
    delete notifier_;
    delete help_overlay_;
}

void UIManager::initialize(SDL_Renderer* renderer, ThemeManager* theme_manager,
                          int physical_width, int physical_height) {
    renderer_ = renderer;
    theme_manager_ = theme_manager;
    physical_window_width_ = physical_width;
    physical_window_height_ = physical_height;

    // Calcular tamaño de fuente apropiado según dimensiones físicas
    current_font_size_ = calculateFontSize(physical_width, physical_height);

    // Crear renderers de texto
    text_renderer_ = new TextRenderer();
    text_renderer_debug_ = new TextRenderer();
    text_renderer_notifier_ = new TextRenderer();

    // Inicializar renderers con tamaño dinámico
    text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", current_font_size_, true);
    text_renderer_debug_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", current_font_size_, true);
    text_renderer_notifier_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", current_font_size_, true);

    // Crear y configurar sistema de notificaciones
    notifier_ = new Notifier();
    notifier_->init(renderer, text_renderer_notifier_, theme_manager_,
                   physical_width, physical_height);

    // Crear y configurar sistema de ayuda (overlay)
    help_overlay_ = new HelpOverlay();
    help_overlay_->initialize(renderer, theme_manager_, physical_width, physical_height, current_font_size_);

    // Inicializar FPS counter
    fps_last_time_ = SDL_GetTicks();
    fps_frame_count_ = 0;
    fps_current_ = 0;
}

void UIManager::update(Uint64 current_time, float delta_time) {
    // Calcular FPS
    fps_frame_count_++;
    if (current_time - fps_last_time_ >= 1000) {  // Actualizar cada segundo
        fps_current_ = fps_frame_count_;
        fps_frame_count_ = 0;
        fps_last_time_ = current_time;
        fps_text_ = "fps: " + std::to_string(fps_current_);
    }

    // Actualizar texto obsoleto (DEPRECATED)
    if (show_text_) {
        show_text_ = !(SDL_GetTicks() - text_init_time_ > TEXT_DURATION);
    }

    // Actualizar sistema de notificaciones
    notifier_->update(current_time);
}

void UIManager::render(SDL_Renderer* renderer,
                      const Engine* engine,
                      const SceneManager* scene_manager,
                      SimulationMode current_mode,
                      AppMode current_app_mode,
                      const Shape* active_shape,
                      float shape_convergence,
                      int physical_width,
                      int physical_height,
                      int current_screen_width) {
    // Actualizar dimensiones físicas (puede cambiar en fullscreen)
    physical_window_width_ = physical_width;
    physical_window_height_ = physical_height;

    // Renderizar texto obsoleto centrado (DEPRECATED - mantener temporalmente)
    if (show_text_) {
        renderObsoleteText(current_screen_width);
    }

    // Renderizar debug HUD si está activo
    if (show_debug_) {
        renderDebugHUD(engine, scene_manager, current_mode, current_app_mode,
                      active_shape, shape_convergence);
    }

    // Renderizar notificaciones (siempre al final, sobre todo lo demás)
    notifier_->render();

    // Renderizar ayuda (siempre última, sobre todo incluso notificaciones)
    if (help_overlay_) {
        help_overlay_->render(renderer);
    }
}

void UIManager::toggleDebug() {
    show_debug_ = !show_debug_;
}

void UIManager::toggleHelp() {
    if (help_overlay_) {
        help_overlay_->toggle();
    }
}

void UIManager::showNotification(const std::string& text, Uint64 duration) {
    if (duration == 0) {
        duration = NOTIFICATION_DURATION;
    }
    notifier_->show(text, duration);
}

void UIManager::updateVSyncText(bool enabled) {
    vsync_text_ = enabled ? "V-Sync: On" : "V-Sync: Off";
}

void UIManager::updatePhysicalWindowSize(int width, int height) {
    physical_window_width_ = width;
    physical_window_height_ = height;

    // Calcular nuevo tamaño de fuente apropiado
    int new_font_size = calculateFontSize(width, height);

    // Si el tamaño cambió, reinicializar todos los text renderers
    if (new_font_size != current_font_size_) {
        current_font_size_ = new_font_size;

        // Reinicializar text renderers con nuevo tamaño
        if (text_renderer_) {
            text_renderer_->reinitialize(current_font_size_);
        }
        if (text_renderer_debug_) {
            text_renderer_debug_->reinitialize(current_font_size_);
        }
        if (text_renderer_notifier_) {
            text_renderer_notifier_->reinitialize(current_font_size_);
        }
    }

    // Actualizar help overlay con font size actual Y nuevas dimensiones (atómicamente)
    if (help_overlay_) {
        help_overlay_->updateAll(current_font_size_, width, height);
    }

    // Actualizar otros componentes de UI con nuevas dimensiones
    notifier_->updateWindowSize(width, height);
}

void UIManager::setTextObsolete(const std::string& text, int pos, int current_screen_width) {
    text_ = text;
    text_pos_ = pos;
    text_init_time_ = SDL_GetTicks();
    show_text_ = true;
}

// === Métodos privados ===

void UIManager::renderDebugHUD(const Engine* engine,
                               const SceneManager* scene_manager,
                               SimulationMode current_mode,
                               AppMode current_app_mode,
                               const Shape* active_shape,
                               float shape_convergence) {
    // Obtener altura de línea para espaciado dinámico
    int line_height = text_renderer_debug_->getTextHeight();
    int margin = 8;  // Margen constante en píxeles físicos

    // Obtener viewport actual (en modo letterbox F3 tiene dimensiones más pequeñas)
    // CRÍTICO: Usar dimensiones del VIEWPORT para alineación, no de la ventana física
    SDL_Rect viewport;
    SDL_GetRenderViewport(renderer_, &viewport);

    // ===========================
    // COLUMNA LEFT (Sistema)
    // ===========================
    int left_y = margin;

    // AppMode (antes estaba centrado, ahora va a la izquierda)
    std::string appmode_text;
    SDL_Color appmode_color = {255, 255, 255, 255};  // Blanco por defecto

    if (current_app_mode == AppMode::LOGO) {
        appmode_text = "AppMode: LOGO";
        appmode_color = {255, 128, 0, 255};  // Naranja
    } else if (current_app_mode == AppMode::DEMO) {
        appmode_text = "AppMode: DEMO";
        appmode_color = {255, 165, 0, 255};  // Naranja
    } else if (current_app_mode == AppMode::DEMO_LITE) {
        appmode_text = "AppMode: DEMO LITE";
        appmode_color = {255, 200, 0, 255};  // Amarillo-naranja
    } else {
        appmode_text = "AppMode: SANDBOX";
        appmode_color = {0, 255, 128, 255};  // Verde claro
    }
    text_renderer_debug_->printAbsolute(margin, left_y, appmode_text.c_str(), appmode_color);
    left_y += line_height;

    // SimulationMode
    std::string simmode_text;
    if (current_mode == SimulationMode::PHYSICS) {
        simmode_text = "SimMode: PHYSICS";
    } else if (current_mode == SimulationMode::SHAPE) {
        if (active_shape) {
            simmode_text = std::string("SimMode: SHAPE (") + active_shape->getName() + ")";
        } else {
            simmode_text = "SimMode: SHAPE";
        }
    } else if (current_mode == SimulationMode::BOIDS) {
        simmode_text = "SimMode: BOIDS";
    }
    text_renderer_debug_->printAbsolute(margin, left_y, simmode_text.c_str(), {0, 255, 255, 255});  // Cian
    left_y += line_height;

    // V-Sync
    text_renderer_debug_->printAbsolute(margin, left_y, vsync_text_.c_str(), {0, 255, 255, 255});  // Cian
    left_y += line_height;

    // Modo de escalado (INTEGER/LETTERBOX/STRETCH o WINDOWED si no está en fullscreen)
    std::string scaling_text;
    if (engine->getFullscreenEnabled() || engine->getRealFullscreenEnabled()) {
        ScalingMode scaling = engine->getCurrentScalingMode();
        if (scaling == ScalingMode::INTEGER) {
            scaling_text = "Scaling: INTEGER";
        } else if (scaling == ScalingMode::LETTERBOX) {
            scaling_text = "Scaling: LETTERBOX";
        } else if (scaling == ScalingMode::STRETCH) {
            scaling_text = "Scaling: STRETCH";
        }
    } else {
        scaling_text = "Scaling: WINDOWED";
    }
    text_renderer_debug_->printAbsolute(margin, left_y, scaling_text.c_str(), {255, 255, 0, 255});  // Amarillo
    left_y += line_height;

    // Resolución física (píxeles reales de la ventana)
    std::string phys_res_text = "Physical: " + std::to_string(physical_window_width_) + "x" + std::to_string(physical_window_height_);
    text_renderer_debug_->printAbsolute(margin, left_y, phys_res_text.c_str(), {255, 128, 255, 255});  // Magenta claro
    left_y += line_height;

    // Resolución lógica (resolución interna del renderizador)
    std::string logic_res_text = "Logical: " + std::to_string(engine->getCurrentScreenWidth()) + "x" + std::to_string(engine->getCurrentScreenHeight());
    text_renderer_debug_->printAbsolute(margin, left_y, logic_res_text.c_str(), {255, 128, 255, 255});  // Magenta claro
    left_y += line_height;

    // Display refresh rate (obtener de SDL)
    std::string refresh_text;
    int num_displays = 0;
    SDL_DisplayID* displays = SDL_GetDisplays(&num_displays);
    if (displays && num_displays > 0) {
        const auto* dm = SDL_GetCurrentDisplayMode(displays[0]);
        if (dm) {
            refresh_text = "Refresh: " + std::to_string(static_cast<int>(dm->refresh_rate)) + " Hz";
        } else {
            refresh_text = "Refresh: N/A";
        }
        SDL_free(displays);
    } else {
        refresh_text = "Refresh: N/A";
    }
    text_renderer_debug_->printAbsolute(margin, left_y, refresh_text.c_str(), {255, 255, 128, 255});  // Amarillo claro
    left_y += line_height;

    // Tema actual (delegado a ThemeManager)
    std::string theme_text = std::string("Theme: ") + theme_manager_->getCurrentThemeNameEN();
    text_renderer_debug_->printAbsolute(margin, left_y, theme_text.c_str(), {128, 255, 255, 255});  // Cian claro
    left_y += line_height;

    // ===========================
    // COLUMNA RIGHT (Primera pelota)
    // ===========================
    int right_y = margin;

    // FPS counter (esquina superior derecha)
    int fps_text_width = text_renderer_debug_->getTextWidthPhysical(fps_text_.c_str());
    int fps_x = viewport.w - fps_text_width - margin;
    text_renderer_debug_->printAbsolute(fps_x, right_y, fps_text_.c_str(), {255, 255, 0, 255});  // Amarillo
    right_y += line_height;

    // Info de la primera pelota (si existe)
    const Ball* first_ball = scene_manager->getFirstBall();
    if (first_ball != nullptr) {
        // Posición X, Y
        SDL_FRect pos = first_ball->getPosition();
        std::string pos_text = "Pos: (" + std::to_string(static_cast<int>(pos.x)) + ", " + std::to_string(static_cast<int>(pos.y)) + ")";
        int pos_width = text_renderer_debug_->getTextWidthPhysical(pos_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - pos_width - margin, right_y, pos_text.c_str(), {255, 128, 128, 255});  // Rojo claro
        right_y += line_height;

        // Velocidad X
        int vx_int = static_cast<int>(first_ball->getVelocityX());
        std::string vx_text = "VelX: " + std::to_string(vx_int);
        int vx_width = text_renderer_debug_->getTextWidthPhysical(vx_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - vx_width - margin, right_y, vx_text.c_str(), {128, 255, 128, 255});  // Verde claro
        right_y += line_height;

        // Velocidad Y
        int vy_int = static_cast<int>(first_ball->getVelocityY());
        std::string vy_text = "VelY: " + std::to_string(vy_int);
        int vy_width = text_renderer_debug_->getTextWidthPhysical(vy_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - vy_width - margin, right_y, vy_text.c_str(), {128, 255, 128, 255});  // Verde claro
        right_y += line_height;

        // Fuerza de gravedad
        int grav_int = static_cast<int>(first_ball->getGravityForce());
        std::string grav_text = "Gravity: " + std::to_string(grav_int);
        int grav_width = text_renderer_debug_->getTextWidthPhysical(grav_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - grav_width - margin, right_y, grav_text.c_str(), {255, 255, 128, 255});  // Amarillo claro
        right_y += line_height;

        // Estado superficie
        std::string surface_text = first_ball->isOnSurface() ? "Surface: YES" : "Surface: NO";
        int surface_width = text_renderer_debug_->getTextWidthPhysical(surface_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - surface_width - margin, right_y, surface_text.c_str(), {255, 200, 128, 255});  // Naranja claro
        right_y += line_height;

        // Coeficiente de rebote (loss)
        float loss_val = first_ball->getLossCoefficient();
        std::string loss_text = "Loss: " + std::to_string(loss_val).substr(0, 4);
        int loss_width = text_renderer_debug_->getTextWidthPhysical(loss_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - loss_width - margin, right_y, loss_text.c_str(), {255, 128, 255, 255});  // Magenta
        right_y += line_height;

        // Dirección de gravedad
        std::string gravity_dir_text = "Dir: " + gravityDirectionToString(static_cast<int>(scene_manager->getCurrentGravity()));
        int dir_width = text_renderer_debug_->getTextWidthPhysical(gravity_dir_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - dir_width - margin, right_y, gravity_dir_text.c_str(), {128, 255, 255, 255});  // Cian claro
        right_y += line_height;
    }

    // Convergencia en modo LOGO (solo cuando está activo) - Parte inferior derecha
    if (current_app_mode == AppMode::LOGO && current_mode == SimulationMode::SHAPE) {
        int convergence_percent = static_cast<int>(shape_convergence * 100.0f);
        std::string convergence_text = "Convergence: " + std::to_string(convergence_percent) + "%";
        int conv_width = text_renderer_debug_->getTextWidthPhysical(convergence_text.c_str());
        text_renderer_debug_->printAbsolute(viewport.w - conv_width - margin, right_y, convergence_text.c_str(), {255, 128, 0, 255});  // Naranja
        right_y += line_height;
    }
}

void UIManager::renderObsoleteText(int current_screen_width) {
    // DEPRECATED: Sistema antiguo de texto centrado
    // Mantener por compatibilidad temporal hasta migrar todo a Notifier

    // Calcular escala dinámica basada en resolución física
    float text_scale_x = static_cast<float>(physical_window_width_) / 426.0f;
    float text_scale_y = static_cast<float>(physical_window_height_) / 240.0f;

    // Obtener color del tema actual (LERP interpolado)
    int margin = 8;
    Color text_color = theme_manager_->getInterpolatedColor(0);
    int text_color_r = text_color.r;
    int text_color_g = text_color.g;
    int text_color_b = text_color.b;

    // Renderizar texto centrado usando coordenadas físicas
    text_renderer_->printPhysical(text_pos_, margin, text_.c_str(),
                                 text_color_r, text_color_g, text_color_b,
                                 text_scale_x, text_scale_y);
}

std::string UIManager::gravityDirectionToString(int direction) const {
    switch (direction) {
        case 0: return "Abajo";   // DOWN
        case 1: return "Arriba";  // UP
        case 2: return "Izquierda"; // LEFT
        case 3: return "Derecha";   // RIGHT
        default: return "Desconocida";
    }
}

int UIManager::calculateFontSize(int physical_width, int physical_height) const {
    // Calcular área física de la ventana
    int area = physical_width * physical_height;

    // Stepped scaling con 3 tamaños:
    // - SMALL: < 800x600 (480,000 pixels) → 14px
    // - MEDIUM: 800x600 a 1920x1080 (2,073,600 pixels) → 18px
    // - LARGE: > 1920x1080 → 24px

    if (area < 480000) {
        return 14;  // Ventanas pequeñas
    } else if (area < 2073600) {
        return 18;  // Ventanas medianas (default)
    } else {
        return 24;  // Ventanas grandes
    }
}
