//
// Shardok-specific game state adapter for MCTS
//

#ifndef EAGLE0_SHARDOK_GAME_STATE_HPP
#define EAGLE0_SHARDOK_GAME_STATE_HPP

#include <memory>

#include "src/main/cpp/net/eagle0/common/mcts/abstract/MCTSGameState.hpp"
#include "src/main/cpp/net/eagle0/shardok/ai/AIStrategy.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/GameStateW.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokEngine.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistancesCache.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/CoordsSet.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"

namespace shardok {

// Forward declarations
class AIScoreCalculator;

namespace mcts {

class ShardokGameState : public MCTSGameState {
public:
    ShardokGameState(
            GameStateW state,
            const AIScoreCalculator* calculator,
            const GameSettings* settings,
            bool isDefender,
            AIStrategy strategy,
            const CoordsSet& castleCoords,
            const APDCache& apdCache,
            const ALCache& alCache,
            const CoordsSet& criticalTileCoords);

    // MCTSGameState interface implementation
    [[nodiscard]] uint64_t hash() const override;
    [[nodiscard]] double score(MCTSPlayerId playerId) const override;
    [[nodiscard]] MCTSPlayerId currentPlayerId() const override;
    [[nodiscard]] bool isTerminal() const override;
    [[nodiscard]] std::unique_ptr<MCTSGameState> clone() const override;
    [[nodiscard]] bool equals(const MCTSGameState& other) const override;
    [[nodiscard]] MCTSPlayerId getWinner() const override;
    [[nodiscard]] std::string toString() const override;

    // Shardok-specific accessors
    [[nodiscard]] const GameStateW& getShardokState() const { return state_; }
    [[nodiscard]] GameStateW& getMutableShardokState() { return state_; }
    [[nodiscard]] bool isDefender() const { return isDefender_; }
    [[nodiscard]] const GameSettings* getSettings() const { return settings_; }
    [[nodiscard]] const CoordsSet& getCriticalTileCoords() const { return criticalTileCoords_; }

    // Engine caching for performance (avoids recomputing available commands)
    void setCachedEngine(std::shared_ptr<ShardokEngine> engine) const { cachedEngine_ = engine; }
    [[nodiscard]] std::shared_ptr<ShardokEngine> getCachedEngine() const { return cachedEngine_; }

    // Invalidate hash cache when state is mutated
    void invalidateHashCache() const {
        hashCached_ = false;
        cachedHash_ = 0;
    }

private:
    GameStateW state_;
    const AIScoreCalculator* scoreCalculator_;
    const GameSettings* settings_;
    bool isDefender_;
    AIStrategy strategy_;
    const CoordsSet castleCoords_;  // Own the data to avoid dangling references
    const APDCache& apdCache_;
    const ALCache& alCache_;
    mutable uint64_t cachedHash_ = 0;
    mutable bool hashCached_ = false;
    const CoordsSet criticalTileCoords_;  // Own the data to avoid dangling references
    mutable std::shared_ptr<ShardokEngine> cachedEngine_;  // Engine with cached available commands
};

}  // namespace mcts
}  // namespace shardok

#endif  // EAGLE0_SHARDOK_GAME_STATE_HPP