//
// AI Battle Simulator - CLI Entry Point
//

#include <filesystem>
#include <iostream>
#include <memory>
#include <string>

#include "AiBattleConfig.hpp"
#include "AiBattleSimulator.hpp"
#include "src/main/cpp/net/eagle0/common/FilesystemUtils.hpp"

using shardok::ai_battle_simulator::AiBattleConfigLoader;
using shardok::ai_battle_simulator::AiBattleSimulator;
using shardok::ai_battle_simulator::BattleResult;

namespace {

void PrintUsage(const char* programName) {
    std::cout << "AI Battle Simulator - AI vs AI Battle Testing Tool\n"
              << "\n"
              << "Usage:\n"
              << "  " << programName << " --config=<path>    Run battle from JSON config file\n"
              << "  " << programName << " --generate-config  Generate sample config to stdout\n"
              << "  " << programName
              << " --generate-config --output=<path>  Generate sample config to file\n"
              << "  " << programName << " --help             Show this help message\n"
              << "\n"
              << "Examples:\n"
              << "  # Generate sample config\n"
              << "  " << programName << " --generate-config > my_battle.json\n"
              << "\n"
              << "  # Run battle from config\n"
              << "  " << programName << " --config=my_battle.json\n"
              << "\n";
}

void GenerateConfigFile(const std::string& outputPath) {
    auto config = AiBattleConfigLoader::CreateDefaultPerfConfig();
    std::string jsonString = AiBattleConfigLoader::ToJsonString(*config);

    if (outputPath.empty() || outputPath == "-") {
        // Output to stdout
        std::cout << jsonString << "\n";
    } else {
        // Output to file
        std::ofstream outFile(outputPath);
        if (!outFile.is_open()) {
            std::cerr << "Error: Failed to open output file: " << outputPath << "\n";
            std::exit(1);
        }
        outFile << jsonString << "\n";
        std::cout << "Sample config written to: " << outputPath << "\n";
    }
}

void RunBattleFromConfig(const std::string& configPath) {
    // Load config
    std::cout << "Loading config from: " << configPath << "\n";
    auto config = AiBattleConfigLoader::LoadFromJsonFile(configPath);

    if (!config) {
        std::cerr << "Error: Failed to load config file\n";
        std::exit(1);
    }

    // Create simulator
    AiBattleSimulator simulator(*config);

    // Run battle
    auto result = simulator.RunBattle();

    // Print results
    std::cout << "\n";
    std::cout << "=================================\n";
    std::cout << "Battle Complete\n";
    std::cout << "=================================\n";
    std::cout << "Winner: ";
    if (result.winner == 0) {
        std::cout << "Attacker (Player 0)\n";
    } else if (result.winner == 1) {
        std::cout << "Defender (Player 1)\n";
    } else {
        std::cout << "Draw\n";
    }
    std::cout << "Result: " << result.description << "\n";
    std::cout << "Total Rounds: " << result.totalRounds << "\n";
    std::cout << "Total Commands: " << result.totalCommands << "\n";

    // Print surviving units
    if (!result.survivingUnits.empty()) {
        std::cout << "\nSurviving Units (" << result.survivingUnits.size() << "):\n";
        for (const auto& unit : result.survivingUnits) {
            std::cout << "  Unit " << unit.unitId << ": " << unit.battalionTypeName << " ("
                      << static_cast<int>(unit.battalionSize) << " troops)";
            if (unit.profession > 0) { std::cout << " - Profession " << unit.profession; }
            std::cout << "\n";
        }
    }

    std::cout << "=================================\n";
}

}  // namespace

int main(int argc, char* argv[]) {
    // Set exec path for FilesystemUtils
    FilesystemUtils::SetExecPath(argv[0]);

    try {
        if (argc < 2) {
            PrintUsage(argv[0]);
            return 1;
        }

        std::string configPath;
        std::string outputPath;
        bool generateConfig = false;

        // Parse command line arguments
        for (int i = 1; i < argc; ++i) {
            std::string arg(argv[i]);

            if (arg == "--help" || arg == "-h") {
                PrintUsage(argv[0]);
                return 0;
            } else if (arg == "--generate-config") {
                generateConfig = true;
            } else if (arg.starts_with("--config=")) {
                configPath = arg.substr(9);
            } else if (arg.starts_with("--output=")) {
                outputPath = arg.substr(9);
            } else {
                std::cerr << "Error: Unknown argument: " << arg << "\n";
                PrintUsage(argv[0]);
                return 1;
            }
        }

        // Execute appropriate action
        if (generateConfig) {
            GenerateConfigFile(outputPath);
        } else if (!configPath.empty()) {
            RunBattleFromConfig(configPath);
        } else {
            std::cerr << "Error: Either --generate-config or --config must be specified\n";
            PrintUsage(argv[0]);
            return 1;
        }

    } catch (const std::exception& e) {
        std::cerr << "Fatal error: " << e.what() << "\n";
        return 1;
    }

    return 0;
}
