#pragma once

#include <random>
#include <string>
#include <vector>

#include <QVector2D>

#include "GameConfig.h"
#include "ShipLayout.h"
#include "Tick.h"

class ShipSystem;

// Manages wave scheduling (tick-order step 1) and threat-level accumulation
// (tick-order step 2). REQ-WAV-*.
class WaveSystem
{
public:
    WaveSystem(const GameConfig& config, std::mt19937& rng);

    // Tick step 1: advance the boss countdown and normal wave gap; trigger
    // normal or boss waves when their timers expire; spawn any ships in the
    // pending queues whose scheduled tick has arrived.
    void tickWaveScheduler(Tick currentTick, ShipSystem& ships,
                           int worldHeightTiles);

    // Tick step 2: accumulate threat from the rate formula evaluated at the
    // current boss wave counter (REQ-WAV-THREAT-RATE).
    void tickThreatAccumulation();

    // Called by Simulation (tick step 9) when the current enemy-station set
    // is fully destroyed: advances the boss countdown and increments generation
    // (REQ-WAV-BOSS-ADVANCE, REQ-PSH-STATION-STATS).
    void onEnemyStationsDestroyed();

    double getThreatLevel() const;

    // Current rate at which getThreatLevel() is increasing, in threat/second
    // (REQ-WAV-THREAT-RATE). 0 during a quiet window (REQ-WAV-QUIET) or when
    // the rate formula evaluates to a negative value.
    double getThreatAccumulationRate() const;

    // Current enemy-station generation level (0 for initial set,
    // incremented by 1 after each push — REQ-PSH-STATION-STATS).
    int getGeneration() const;

    // Boss wave counter (REQ-WAV-BOSS-COUNTER): current cycle number, starts at 1.
    int getBossWaveCounter() const;

    // Ticks remaining until the next boss wave fires (REQ-WAV-BOSS-COUNTDOWN).
    Tick getBossCountdownTicks() const;

    // Ticks remaining on the current normal-wave gap timer (REQ-WAV-GAP).
    // Frozen during quiet windows.
    Tick getNormalGapRemainingTicks() const;

private:
    struct SpawnEntry
    {
        std::string       schematicId;
        Tick              spawnAt;
        QVector2D         position;
        ShipLayoutConfig  layout;
    };

    // Select ships from the given threat budget until no eligible ship fits.
    // Reduces budget in-place to the remaining (carry-over) amount.
    std::vector<SpawnEntry> selectWaveShips(double& budget, Tick currentTick,
                                            int worldHeightTiles);

    void triggerNormalWave(Tick currentTick, int worldHeightTiles);
    void triggerBossWave(Tick currentTick, int worldHeightTiles);

    // Returns true while normal-wave spawning should be suppressed (REQ-WAV-QUIET).
    bool isInQuietWindow() const;

    // Draw a random gap duration in ticks from [gapMin, gapMax].
    Tick drawGapTicks();

    const GameConfig& m_config;
    std::mt19937&     m_rng;

    double m_threatLevel = 0.0;
    int    m_generation  = 0;

    // Boss wave cycle (REQ-WAV-BOSS-COUNTER, REQ-WAV-BOSS-COUNTDOWN).
    int  m_bossWaveCounter             = 1;
    Tick m_bossCountdownTicks;             // counts down each tick; reset after boss fires
    Tick m_postBossQuietRemainingTicks = 0;

    // Normal wave gap — frozen during quiet windows (REQ-WAV-GAP).
    bool m_normalWaveActive        = false;
    Tick m_normalGapRemainingTicks;        // replaces old m_nextEventTick

    // Spawn queues — kept separate so normal-wave completion is trackable.
    std::vector<SpawnEntry> m_normalPendingSpawns;
    std::vector<SpawnEntry> m_bossPendingSpawns;
};
