//
// AI Battle Simulator Configuration Loader Implementation
//

#include "AiBattleConfig.hpp"

#include <google/protobuf/util/json_util.h>

#include <fstream>
#include <iostream>
#include <sstream>

namespace shardok::ai_battle_simulator {

using net::eagle0::shardok::ai_battle_simulator::AIAlgorithmType;
using net::eagle0::shardok::ai_battle_simulator::PlayerConfig;
using net::eagle0::shardok::ai_battle_simulator::UnitConfig;

std::unique_ptr<BattleConfigProto> AiBattleConfigLoader::LoadFromJsonFile(
        const std::string& filepath) {
    std::ifstream file(filepath);
    if (!file.is_open()) {
        std::cerr << "Failed to open config file: " << filepath << '\n';
        return nullptr;
    }

    std::stringstream buffer;
    buffer << file.rdbuf();
    return LoadFromJsonString(buffer.str());
}

std::unique_ptr<BattleConfigProto> AiBattleConfigLoader::LoadFromJsonString(
        const std::string& jsonString) {
    auto config = std::make_unique<BattleConfigProto>();

    google::protobuf::util::JsonParseOptions options;
    options.ignore_unknown_fields = false;

    const auto status =
            google::protobuf::util::JsonStringToMessage(jsonString, config.get(), options);

    if (!status.ok()) {
        std::cerr << "Failed to parse JSON config: " << status.message() << '\n';
        return nullptr;
    }

    return config;
}

std::unique_ptr<BattleConfigProto> AiBattleConfigLoader::CreateDefaultPerfConfig(int month) {
    auto config = std::make_unique<BattleConfigProto>();

    // Basic setup matching Unity's "Perf" configuration
    config->set_map_name("Alah");
    config->set_month(month);
    config->set_max_rounds(31);
    config->set_random_seed(1);
    config->set_use_configured_placements(false);
    config->set_apply_forced_commands(true);

    // Attacker configuration - 6 Longbowmen units with professions 1-6
    PlayerConfig* attacker = config->mutable_attacker();
    attacker->set_ai_algorithm(AIAlgorithmType::ITERATIVE_DEEPENING);
    attacker->set_scoring_calculator(
            net::eagle0::shardok::ai_battle_simulator::ScoringCalculatorType::STANDARD);

    for (int profession = 1; profession <= 6; ++profession) {
        UnitConfig* unit = attacker->add_units();
        unit->set_profession(profession);
        unit->set_battalion_type_id(4);        // Longbowmen (battalion type 4)
        unit->set_starting_position_index(0);  // Attackers use position 0
        unit->set_can_flee(true);
        unit->mutable_battalion()->set_size(1000);  // Match client battalion size
    }

    // Defender configuration - 6 Light Infantry units with NO_PROFESSION (profession 14)
    PlayerConfig* defender = config->mutable_defender();
    defender->set_ai_algorithm(AIAlgorithmType::ITERATIVE_DEEPENING);
    defender->set_scoring_calculator(
            net::eagle0::shardok::ai_battle_simulator::ScoringCalculatorType::STANDARD);

    for (int i = 0; i < 6; ++i) {
        UnitConfig* unit = defender->add_units();
        unit->set_profession(14);               // NO_PROFESSION to match client battles
        unit->set_battalion_type_id(0);         // Light Infantry (battalion type 0)
        unit->set_starting_position_index(-1);  // Defenders use position -1
        unit->set_can_flee(true);
        unit->mutable_battalion()->set_size(1000);  // Match client battalion size
    }

    return config;
}

std::string AiBattleConfigLoader::ToJsonString(const BattleConfigProto& config) {
    std::string jsonString;

    google::protobuf::util::JsonPrintOptions options;
    options.add_whitespace = true;
    options.always_print_fields_with_no_presence = true;
    options.preserve_proto_field_names = true;

    const auto status = google::protobuf::util::MessageToJsonString(config, &jsonString, options);

    if (!status.ok()) {
        std::cerr << "Failed to convert config to JSON: " << status.message() << '\n';
        return "";
    }

    return jsonString;
}

}  // namespace shardok::ai_battle_simulator
