// stage_manager.cpp - Implementació del gestor d'stages
// © 2025 Orni Attack

#include "stage_manager.hpp"

#include <iostream>

#include "core/audio/audio.hpp"
#include "core/defaults.hpp"

namespace StageSystem {

StageManager::StageManager(const ConfigSistemaStages* config)
    : config_(config),
      estat_(EstatStage::LEVEL_START),
      stage_actual_(1),
      timer_transicio_(0.0f) {
    if (!config_) {
        std::cerr << "[StageManager] Error: config és null" << std::endl;
    }
}

void StageManager::inicialitzar() {
    stage_actual_ = 1;
    carregar_stage(stage_actual_);
    canviar_estat(EstatStage::INIT_HUD);

    std::cout << "[StageManager] Inicialitzat a stage " << static_cast<int>(stage_actual_)
              << std::endl;
}

void StageManager::actualitzar(float delta_time, bool pausar_spawn) {
    switch (estat_) {
        case EstatStage::INIT_HUD:
            processar_init_hud(delta_time);
            break;

        case EstatStage::LEVEL_START:
            processar_level_start(delta_time);
            break;

        case EstatStage::PLAYING:
            processar_playing(delta_time, pausar_spawn);
            break;

        case EstatStage::LEVEL_COMPLETED:
            processar_level_completed(delta_time);
            break;
    }
}

void StageManager::stage_completat() {
    std::cout << "[StageManager] Stage " << static_cast<int>(stage_actual_) << " completat!"
              << std::endl;
    canviar_estat(EstatStage::LEVEL_COMPLETED);
}

bool StageManager::tot_completat() const {
    return stage_actual_ >= config_->metadata.total_stages &&
        estat_ == EstatStage::LEVEL_COMPLETED &&
        timer_transicio_ <= 0.0f;
}

const ConfigStage* StageManager::get_config_actual() const {
    return config_->obte_stage(stage_actual_);
}

void StageManager::canviar_estat(EstatStage nou_estat) {
    estat_ = nou_estat;

    // Set timer based on state type
    if (nou_estat == EstatStage::INIT_HUD) {
        timer_transicio_ = Defaults::Game::INIT_HUD_DURATION;
    } else if (nou_estat == EstatStage::LEVEL_START) {
        timer_transicio_ = Defaults::Game::LEVEL_START_DURATION;
    } else if (nou_estat == EstatStage::LEVEL_COMPLETED) {
        timer_transicio_ = Defaults::Game::LEVEL_COMPLETED_DURATION;
    }

    // Select random message when entering LEVEL_START
    if (nou_estat == EstatStage::LEVEL_START) {
        size_t index = static_cast<size_t>(std::rand()) % Constants::MISSATGES_LEVEL_START.size();
        missatge_level_start_actual_ = Constants::MISSATGES_LEVEL_START[index];

        // [NOU] Iniciar música al entrar en LEVEL_START (després de INIT_HUD)
        // Només si no està sonant ja (per evitar reiniciar en loops posteriors)
        if (Audio::get()->getMusicState() != Audio::MusicState::PLAYING) {
            Audio::get()->playMusic("game.ogg");
        }
    }

    std::cout << "[StageManager] Canvi d'estat: ";
    switch (nou_estat) {
        case EstatStage::INIT_HUD:
            std::cout << "INIT_HUD";
            break;
        case EstatStage::LEVEL_START:
            std::cout << "LEVEL_START";
            break;
        case EstatStage::PLAYING:
            std::cout << "PLAYING";
            break;
        case EstatStage::LEVEL_COMPLETED:
            std::cout << "LEVEL_COMPLETED";
            break;
    }
    std::cout << std::endl;
}

void StageManager::processar_init_hud(float delta_time) {
    timer_transicio_ -= delta_time;

    if (timer_transicio_ <= 0.0f) {
        canviar_estat(EstatStage::LEVEL_START);
    }
}

void StageManager::processar_level_start(float delta_time) {
    timer_transicio_ -= delta_time;

    if (timer_transicio_ <= 0.0f) {
        canviar_estat(EstatStage::PLAYING);
    }
}

void StageManager::processar_playing(float delta_time, bool pausar_spawn) {
    // Update spawn controller (pauses when pausar_spawn = true)
    // Note: The actual enemy array update happens in EscenaJoc::actualitzar()
    // This is just for internal timekeeping
    (void)delta_time;    // Spawn controller is updated externally
    (void)pausar_spawn;  // Passed to spawn_controller_.actualitzar() by EscenaJoc
}

void StageManager::processar_level_completed(float delta_time) {
    timer_transicio_ -= delta_time;

    if (timer_transicio_ <= 0.0f) {
        // Advance to next stage
        stage_actual_++;

        // Loop back to stage 1 after final stage
        if (stage_actual_ > config_->metadata.total_stages) {
            stage_actual_ = 1;
            std::cout << "[StageManager] Totes les stages completades! Tornant a stage 1"
                      << std::endl;
        }

        // Load next stage
        carregar_stage(stage_actual_);
        canviar_estat(EstatStage::LEVEL_START);
    }
}

void StageManager::carregar_stage(uint8_t stage_id) {
    const ConfigStage* stage_config = config_->obte_stage(stage_id);
    if (!stage_config) {
        std::cerr << "[StageManager] Error: no es pot trobar stage " << static_cast<int>(stage_id)
                  << std::endl;
        return;
    }

    // Configure spawn controller
    spawn_controller_.configurar(stage_config);
    spawn_controller_.iniciar();

    std::cout << "[StageManager] Carregat stage " << static_cast<int>(stage_id) << ": "
              << static_cast<int>(stage_config->total_enemics) << " enemics" << std::endl;
}

}  // namespace StageSystem
