//
// GameStateDumper.cpp
// Utility for dumping game state to file for debugging
//

#include "GameStateDumper.hpp"

#include <fstream>
#include <iostream>

namespace shardok {

void DumpGameStateToFile(const GameStateW& gameState, const std::string& gameId) {
    const std::string filePath = "/tmp/shardok_setup_complete_" + gameId + ".txt";
    std::ofstream out(filePath);
    if (!out.is_open()) {
        std::cerr << "Failed to open " << filePath << " for writing\n";
        return;
    }

    out << "==================== GAME STATE DUMP ====================\n\n";
    out << "Game ID: " << gameId << "\n\n";

    // Game status
    out << "Current Player: " << static_cast<int>(gameState->current_player()) << "\n";
    out << "Current Round: " << static_cast<int>(gameState->current_round()) << "\n";
    out << "Game State: ";
    switch (gameState->status()->state()) {
        case net::eagle0::shardok::storage::fb::GameStatus_::State_SET_UP: out << "SET_UP\n"; break;
        case net::eagle0::shardok::storage::fb::GameStatus_::State_GAME_RUNNING:
            out << "GAME_RUNNING\n";
            break;
        case net::eagle0::shardok::storage::fb::GameStatus_::State_VICTORY:
            out << "VICTORY\n";
            break;
        case net::eagle0::shardok::storage::fb::GameStatus_::State_DRAW: out << "DRAW\n"; break;
        default: out << "UNKNOWN\n";
    }
    out << "\n";

    // Units
    out << "==================== UNITS ====================\n\n";
    const auto* units = gameState->units();
    if (units) {
        for (const auto* unit : *units) {
            if (!unit) continue;

            out << "Unit ID: " << unit->unit_id() << "\n";
            out << "  Player ID: " << static_cast<int>(unit->player_id()) << "\n";
            out << "  Location: (" << static_cast<int>(unit->location().row()) << ", "
                << static_cast<int>(unit->location().column()) << ")\n";
            out << "  Starting Position Index: "
                << static_cast<int>(unit->starting_position_index()) << "\n";
            out << "  Status: ";
            switch (unit->status()) {
                case net::eagle0::shardok::storage::fb::UnitStatus_NORMAL_UNIT:
                    out << "NORMAL_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_RESERVE_UNIT:
                    out << "RESERVE_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_NEVER_ENTERED_UNIT:
                    out << "NEVER_ENTERED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_FLED_UNIT:
                    out << "FLED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_CAPTURED_UNIT:
                    out << "CAPTURED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_DESTROYED_SUMMONED_UNIT:
                    out << "DESTROYED_SUMMONED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_RETREATED_UNIT:
                    out << "RETREATED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_EVACUATED_UNIT:
                    out << "EVACUATED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_SECURED_UNIT:
                    out << "SECURED_UNIT\n";
                    break;
                case net::eagle0::shardok::storage::fb::UnitStatus_PENDING_REINFORCEMENT:
                    out << "PENDING_REINFORCEMENT\n";
                    break;
                default: out << "OTHER (" << static_cast<int>(unit->status()) << ")\n";
            }
            out << "  Remaining Action Points: "
                << static_cast<int>(unit->remaining_action_points()) << "\n";
            out << "  Can Flee: " << (unit->can_flee() ? "true" : "false") << "\n";
            out << "  Fortified: " << (unit->fortified() ? "true" : "false") << "\n";
            out << "  Hidden: " << (unit->hidden() ? "true" : "false") << "\n";

            // Battalion info
            const auto& battalion = unit->battalion();
            out << "  Battalion Type: " << static_cast<int>(battalion.type()) << "\n";
            out << "  Battalion Size: " << battalion.size() << "\n";
            out << "  Battalion Armament: " << battalion.armament() << "\n";
            out << "  Battalion Training: " << battalion.training() << "\n";
            out << "  Battalion Morale: " << battalion.morale() << "\n";

            // Hero info
            if (unit->has_attached_hero()) {
                const auto& hero = unit->attached_hero();
                out << "  Has Hero: true\n";
                out << "    Profession: " << static_cast<int>(hero.profession_info().profession())
                    << "\n";
                out << "    Strength: " << static_cast<int>(hero.strength()) << "\n";
                out << "    Agility: " << static_cast<int>(hero.agility()) << "\n";
                out << "    Wisdom: " << static_cast<int>(hero.wisdom()) << "\n";
                out << "    Charisma: " << static_cast<int>(hero.charisma()) << "\n";
                out << "    Constitution: " << static_cast<int>(hero.constitution()) << "\n";
                out << "    Bravery: " << static_cast<int>(hero.bravery()) << "\n";
                out << "    Integrity: " << static_cast<int>(hero.integrity()) << "\n";
                out << "    Ambition: " << static_cast<int>(hero.ambition()) << "\n";
                out << "    Vigor: " << static_cast<int>(hero.vigor()) << "/"
                    << static_cast<int>(hero.starting_vigor()) << "\n";
            } else {
                out << "  Has Hero: false\n";
            }

            // Opponent knowledge
            out << "  Opponent Knowledge:\n";
            const auto* opponentKnowledge = unit->opponent_knowledge();
            if (opponentKnowledge && opponentKnowledge->size() >= 2) {
                out << "    Player 0: " << static_cast<int>(opponentKnowledge->Get(0)) << "\n";
                out << "    Player 1: " << static_cast<int>(opponentKnowledge->Get(1)) << "\n";
            }

            out << "\n";
        }
    }

    out << "==================== END DUMP ====================\n";
    out.close();

    std::cout << "Game state after setup dumped to " << filePath << "\n";
}

}  // namespace shardok
