#pragma once

#include <SDL3/SDL.h>  // Para Uint32, SDL_FRect

#include <array>   // Para array
#include <string>  // Para basic_string, string

#include "core/system/defaults.hpp"  // Para los valores por defecto
#include "game/ui/notifier.hpp"      // Para Notifier::Position
#include "utils/color.hpp"           // Para Color, Zone
#include "utils/utils.hpp"

// --- Parámetros del juego ---
struct ParamGame {
    float width = Defaults::Game::WIDTH;
    float height = Defaults::Game::HEIGHT;
    Zone play_area{};  // Se inicializa en el constructor de Param
    Zone game_area{};  // Se inicializa en el constructor de Param
    int name_entry_idle_time = Defaults::Game::NAME_ENTRY_IDLE_TIME;
    int name_entry_total_time = Defaults::Game::NAME_ENTRY_TOTAL_TIME;
    Color item_text_outline_color;
};

// --- Parámetros del fade ---
struct ParamFade {
    Color color = Color::fromHex(Defaults::Fade::COLOR);
    float num_squares_width = Defaults::Fade::NUM_SQUARES_WIDTH;
    float num_squares_height = Defaults::Fade::NUM_SQUARES_HEIGHT;
    int random_squares_duration_ms = Defaults::Fade::RANDOM_SQUARES_DURATION_MS;
    int post_duration_ms = Defaults::Fade::POST_DURATION_MS;
    float venetian_size = Defaults::Fade::VENETIAN_SIZE;
};

// --- Parámetros de la pantalla de título ---
struct ParamTitle {
    int press_start_position = Defaults::Title::PRESS_START_POSITION;
    float title_duration = Defaults::Title::DURATION_S;
    int arcade_edition_position = Defaults::Title::ARCADE_EDITION_POSITION;
    int title_c_c_position = Defaults::Title::TITLE_C_C_POSITION;
    Color bg_color = Color::fromHex(Defaults::Title::BG_COLOR);
};

// --- Parámetros del fondo ---
struct ParamBackground {
    Color attenuate_color = Color::fromHex(Defaults::Background::ATTENUATE_COLOR);
};

// --- Parámetros de los globos ---
struct ParamBalloon {
    struct Settings {
        float grav;
        float vel;

        // Constructor por defecto
        constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F)
            : grav(grav_val),
              vel(vel_val) {}
    };

    std::array<Settings, 4> settings = {{Settings(Defaults::Balloon::SETTINGS[0].grav, Defaults::Balloon::SETTINGS[0].vel),
        Settings(Defaults::Balloon::SETTINGS[1].grav, Defaults::Balloon::SETTINGS[1].vel),
        Settings(Defaults::Balloon::SETTINGS[2].grav, Defaults::Balloon::SETTINGS[2].vel),
        Settings(Defaults::Balloon::SETTINGS[3].grav, Defaults::Balloon::SETTINGS[3].vel)}};

    std::array<std::string, 4> color = {{Defaults::Balloon::COLORS[0],
        Defaults::Balloon::COLORS[1],
        Defaults::Balloon::COLORS[2],
        Defaults::Balloon::COLORS[3]}};

    bool bouncing_sound = Defaults::Balloon::BOUNCING_SOUND;
};

// --- Parámetros de las notificaciones ---
struct ParamNotification {
    Notifier::Position pos_h = Defaults::Notification::POS_H;
    Notifier::Position pos_v = Defaults::Notification::POS_V;
    bool sound = Defaults::Notification::SOUND;
    Color color = Color::fromHex(Defaults::Notification::COLOR);
};

// --- Parámetros del marcador ---
struct ParamScoreboard {
    SDL_FRect rect = {
        .x = Defaults::Scoreboard::RECT_X,
        .y = Defaults::Scoreboard::RECT_Y,
        .w = Defaults::Scoreboard::RECT_W,
        .h = Defaults::Scoreboard::RECT_H};
    bool separator_autocolor = Defaults::Scoreboard::SEPARATOR_AUTOCOLOR;
    Color separator_color = Color::fromHex(Defaults::Scoreboard::SEPARATOR_COLOR);
    Color easy_color = Color::fromHex(Defaults::Scoreboard::EASY_COLOR);
    Color normal_color = Color::fromHex(Defaults::Scoreboard::NORMAL_COLOR);
    Color hard_color = Color::fromHex(Defaults::Scoreboard::HARD_COLOR);
    bool text_autocolor = Defaults::Scoreboard::TEXT_AUTOCOLOR;
    Color text_color1 = Color::fromHex(Defaults::Scoreboard::TEXT_COLOR1);
    Color text_color2 = Color::fromHex(Defaults::Scoreboard::TEXT_COLOR2);
    int skip_countdown_value = Defaults::Scoreboard::SKIP_COUNTDOWN_VALUE;
};

// --- Parámetros del menú de servicio ---
struct ParamServiceMenu {
    Color title_color = Color::fromHex(Defaults::ServiceMenu::TITLE_COLOR);
    Color text_color = Color::fromHex(Defaults::ServiceMenu::TEXT_COLOR);
    Color selected_color = Color::fromHex(Defaults::ServiceMenu::SELECTED_COLOR);
    Color bg_color = Color::fromHex(Defaults::ServiceMenu::BG_COLOR);
    bool drop_shadow = Defaults::ServiceMenu::DROP_SHADOW;

    // Configuración para ventanas de mensaje
    struct WindowMessage {
        Color bg_color = Color::fromHex(Defaults::ServiceMenu::WindowMessage::BG_COLOR);
        Color border_color = Color::fromHex(Defaults::ServiceMenu::WindowMessage::BORDER_COLOR);
        Color title_color = Color::fromHex(Defaults::ServiceMenu::WindowMessage::TITLE_COLOR);
        Color text_color = Color::fromHex(Defaults::ServiceMenu::WindowMessage::TEXT_COLOR);
        float padding = Defaults::ServiceMenu::WindowMessage::PADDING;
        float line_spacing = Defaults::ServiceMenu::WindowMessage::LINE_SPACING;
        float title_separator_spacing = Defaults::ServiceMenu::WindowMessage::TITLE_SEPARATOR_SPACING;
        float min_width = Defaults::ServiceMenu::WindowMessage::MIN_WIDTH;
        float min_height = Defaults::ServiceMenu::WindowMessage::MIN_HEIGHT;
        float max_width_ratio = Defaults::ServiceMenu::WindowMessage::MAX_WIDTH_RATIO;
        float max_height_ratio = Defaults::ServiceMenu::WindowMessage::MAX_HEIGHT_RATIO;
        float text_safety_margin = Defaults::ServiceMenu::WindowMessage::TEXT_SAFETY_MARGIN;
        float animation_duration = Defaults::ServiceMenu::WindowMessage::ANIMATION_DURATION;
    } window_message;
};

// --- Parámetros de la intro ---
struct ParamIntro {
    Color bg_color = Color::fromHex(Defaults::Intro::BG_COLOR);
    Color card_color = Color::fromHex(Defaults::Intro::CARD_COLOR);
    Color shadow_color = Color::fromHex(Defaults::Intro::SHADOW_COLOR);
    int text_distance_from_bottom = Defaults::Intro::TEXT_DISTANCE_FROM_BOTTOM;
};

// --- Parámetros para Debug ---
struct ParamDebug {
    Color color = Color::fromHex(Defaults::Debug::COLOR);
};

// --- Parámetros para Resource ---
struct ParamResource {
    Color color = Color::fromHex(Defaults::Resource::COLOR);
};

// --- Parámetros para Tabe ---
struct ParamTabe {
    float min_spawn_time = Defaults::Tabe::MIN_SPAWN_TIME;
    float max_spawn_time = Defaults::Tabe::MAX_SPAWN_TIME;
};

// --- Parámetros del Jugador ---
struct ParamPlayer {
    // Configuración de camisetas del jugador
    struct Shirt {
        Color darkest;  // Tono más oscuro - bordes y contornos
        Color dark;     // Tono oscuro - sombras
        Color base;     // Tono principal - color base de la camiseta
        Color light;    // Tono claro - zonas iluminadas/highlights

        // Constructor por defecto
        Shirt() = default;

        // Constructor con tonalidades específicas
        Shirt(const Color& darkest_tone, const Color& dark_tone, const Color& base_tone, const Color& light_tone)
            : darkest(darkest_tone),
              dark(dark_tone),
              base(base_tone),
              light(light_tone) {}
    };

    // Inicialización con valores por defecto
    const Shirt default_player0_shirt = Shirt(
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER0_DARKEST),
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER0_DARK),
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER0_BASE),
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER0_LIGHT));

    const Shirt default_player1_shirt = Shirt(
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER1_DARKEST),
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER1_DARK),
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER1_BASE),
        Color::fromHex(Defaults::Player::DefaultShirt::PLAYER1_LIGHT));

    std::array<Shirt, 2> default_shirt = {default_player0_shirt, default_player1_shirt};

    const Shirt one_coffee_player0_shirt = Shirt(
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER0_DARKEST),
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER0_DARK),
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER0_BASE),
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER0_LIGHT));

    const Shirt one_coffee_player1_shirt = Shirt(
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER1_DARKEST),
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER1_DARK),
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER1_BASE),
        Color::fromHex(Defaults::Player::OneCoffeeShirt::PLAYER1_LIGHT));

    std::array<Shirt, 2> one_coffee_shirt = {one_coffee_player0_shirt, one_coffee_player1_shirt};

    const Shirt two_coffee_player0_shirt = Shirt(
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER0_DARKEST),
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER0_DARK),
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER0_BASE),
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER0_LIGHT));

    const Shirt two_coffee_player1_shirt = Shirt(
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER1_DARKEST),
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER1_DARK),
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER1_BASE),
        Color::fromHex(Defaults::Player::TwoCoffeeShirt::PLAYER1_LIGHT));

    std::array<Shirt, 2> two_coffee_shirt = {two_coffee_player0_shirt, two_coffee_player1_shirt};

    const Color outline_player0_color = Color::fromHex(Defaults::Player::OutlineColor::PLAYER0);
    const Color outline_player1_color = Color::fromHex(Defaults::Player::OutlineColor::PLAYER1);
    std::array<Color, 2> outline_color = {outline_player0_color, outline_player1_color};
};

// --- Estructura Param: almacena todos los parámetros del juego ---
struct Param {
    ParamGame game;
    ParamFade fade;
    ParamScoreboard scoreboard;
    ParamTitle title;
    ParamBackground background;
    ParamBalloon balloon;
    ParamNotification notification;
    ParamServiceMenu service_menu;
    ParamIntro intro;
    ParamDebug debug;
    ParamResource resource;
    ParamTabe tabe;
    ParamPlayer player;

    // Constructor que inicializa las zonas que dependen de otros valores
    Param() {
        // Inicializar play_area usando los valores por defecto
        game.play_area.rect = {
            .x = Defaults::Game::PLAY_AREA_X,
            .y = Defaults::Game::PLAY_AREA_Y,
            .w = Defaults::Game::PLAY_AREA_W,
            .h = Defaults::Game::PLAY_AREA_H};

        // Las zonas calculadas se inicializarán en precalculateZones()
        precalculateZones();
    }

    // Función pública para recalcular zonas (necesaria después de cambiar parámetros)
    void precalculateZones();
};

// --- Variables ---
extern Param param;  // Variable global con los parámetros del juego

// --- Funciones ---
void loadParamsFromFile(const std::string& file_path);  // Carga parámetros desde archivo