//
// AI Battle Simulator - Runs AI vs AI battles to completion
//

#ifndef EAGLE0_AI_BATTLE_SIMULATOR_HPP
#define EAGLE0_AI_BATTLE_SIMULATOR_HPP

#include <memory>
#include <string>
#include <vector>

#include "src/main/cpp/net/eagle0/shardok/library/GameStateW.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
#include "src/main/flatbuffer/net/eagle0/shardok/storage/hex_map.hpp"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-redundant-constexpr-static-def"
#include "src/main/protobuf/net/eagle0/shardok/ai_battle_simulator/ai_battle_config.pb.h"
#pragma clang diagnostic pop

namespace shardok {

// Forward declarations
class ShardokAIClient;
class ShardokEngine;

// Type alias for hex map
using HexMap = net::eagle0::shardok::storage::fb::HexMap;

namespace ai_battle_simulator {

using BattleConfigProto = net::eagle0::shardok::ai_battle_simulator::BattleConfig;

// Information about a surviving unit
struct SurvivingUnit {
    int unitId;
    std::string battalionTypeName;
    double battalionSize;
    int profession;  // 0 if no hero
};

// Result of a complete battle simulation
struct BattleResult {
    // Winner's player ID (-1 if draw)
    PlayerId winner;

    // Total number of rounds played
    int totalRounds;

    // Total number of commands executed
    int totalCommands;

    // How the game ended
    enum class EndReason {
        LAST_PLAYER_STANDING,       // One player eliminated all opponent units
        CRITICAL_TILES_CONTROLLED,  // Attacker controlled critical tiles
        MAX_ROUNDS_REACHED,         // Defender won by surviving max rounds
        DRAW                        // Game ended in a draw
    };
    EndReason endReason;

    // Human-readable description of the result
    std::string description;

    // Surviving units (for the winner, or all units if draw)
    std::vector<SurvivingUnit> survivingUnits;
};

class AiBattleSimulator {
public:
    /**
     * Initialize the simulator with a battle configuration.
     *
     * @param config The battle configuration
     * @param gameSettings The game settings to use (if nullptr, will initialize default)
     */
    explicit AiBattleSimulator(
            const BattleConfigProto& config,
            GameSettingsSPtr gameSettings = nullptr);

    /**
     * Run the battle from start to completion.
     * This includes:
     * 1. Setup phase (placing units)
     * 2. Battle phase (combat until victory/defeat/draw)
     *
     * @return BattleResult containing winner and statistics
     */
    [[nodiscard]] BattleResult RunBattle();

private:
    // Configuration
    const BattleConfigProto config_;
    GameSettingsSPtr gameSettings_;

    // Game state builder and helpers
    [[nodiscard]] GameStateW CreateInitialGameState() const;
    [[nodiscard]] std::unique_ptr<ShardokAIClient> CreateAIClient(
            PlayerId playerId,
            const HexMap* hexMap) const;

    // Game loop helpers
    [[nodiscard]] BattleResult
    RunSetupPhase(ShardokEngine& engine, ShardokAIClient& attackerAI, ShardokAIClient& defenderAI);

    [[nodiscard]] BattleResult
    RunBattlePhase(ShardokEngine& engine, ShardokAIClient& attackerAI, ShardokAIClient& defenderAI);

    [[nodiscard]] bool IsGameOver(const GameStateW& state) const;
    [[nodiscard]] BattleResult
    CreateResultFromGameState(const GameStateW& state, int totalRounds, int totalCommands) const;
};

}  // namespace ai_battle_simulator
}  // namespace shardok

#endif  // EAGLE0_AI_BATTLE_SIMULATOR_HPP
