#include "game/options.hpp"

#include <fstream>
#include <iostream>
#include <string>

#include "external/fkyaml_node.hpp"
#include "game/defaults.hpp"
#include "game/defines.hpp"

namespace Options {

    // Estableix la ruta del fitxer de configuració
    void setConfigFile(const std::string& path) {
        config_file_path = path;
    }

    // --- Funcions helper de càrrega ---

    static void loadAudioConfigFromYaml(const fkyaml::node& yaml) {
        if (!yaml.contains("audio")) return;
        const auto& node = yaml["audio"];

        if (node.contains("volume"))
            audio.volume = node["volume"].get_value<float>();

        if (node.contains("music")) {
            const auto& music = node["music"];
            if (music.contains("enabled"))
                audio.music_enabled = music["enabled"].get_value<bool>();
            if (music.contains("volume"))
                audio.music_volume = music["volume"].get_value<float>();
        }

        if (node.contains("sound")) {
            const auto& sound = node["sound"];
            if (sound.contains("enabled"))
                audio.sound_enabled = sound["enabled"].get_value<bool>();
            if (sound.contains("volume"))
                audio.sound_volume = sound["volume"].get_value<float>();
        }
    }

    static void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
        if (!yaml.contains("window")) return;
        const auto& node = yaml["window"];

        if (node.contains("zoom"))
            window.zoom = node["zoom"].get_value<int>();
        if (node.contains("fullscreen"))
            window.fullscreen = node["fullscreen"].get_value<bool>();
    }

    static void loadGameConfigFromYaml(const fkyaml::node& yaml) {
        if (!yaml.contains("game")) return;
        const auto& node = yaml["game"];

        if (node.contains("habitacio_inicial"))
            game.habitacio_inicial = node["habitacio_inicial"].get_value<int>();
        if (node.contains("piramide_inicial"))
            game.piramide_inicial = node["piramide_inicial"].get_value<int>();
        if (node.contains("vides"))
            game.vides = node["vides"].get_value<int>();
    }

    // Carrega les opcions des del fitxer configurat
    auto loadFromFile() -> bool {
        const std::string CONFIG_VERSION = Texts::VERSION;
        version = "";

        std::ifstream file(config_file_path);
        if (!file.good()) {
            std::cout << "Config file not found, creating default: " << config_file_path << '\n';
            saveToFile();
            return true;
        }

        std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
        file.close();

        try {
            std::cout << "Reading config file: " << config_file_path << '\n';

            auto yaml = fkyaml::node::deserialize(content);

            if (yaml.contains("version")) {
                version = yaml["version"].get_value<std::string>();
            }

            if (CONFIG_VERSION != version) {
                std::cout << "Config version mismatch (expected: " << CONFIG_VERSION
                          << ", got: " << version << "), creating new config\n";
                saveToFile();
                return true;
            }

            loadWindowConfigFromYaml(yaml);
            loadAudioConfigFromYaml(yaml);
            loadGameConfigFromYaml(yaml);

            std::cout << "Config file loaded successfully\n\n";
            return true;

        } catch (const fkyaml::exception& e) {
            std::cerr << "Error parsing YAML config: " << e.what() << '\n';
            std::cerr << "Creating new config with defaults\n";
            saveToFile();
            return true;
        }
    }

    // Guarda les opcions al fitxer configurat
    auto saveToFile() -> bool {
        std::ofstream file(config_file_path);
        if (!file.is_open()) {
            std::cerr << "Error: Unable to open file " << config_file_path << " for writing\n";
            return false;
        }

        std::cout << "Writing config file: " << config_file_path << '\n';

        file << "# Aventures En Egipte - Configuration File\n";
        file << "# \n";
        file << "# This file is automatically generated and managed by the game.\n";
        file << "# Manual edits are preserved if valid.\n";
        file << "\n";

        // VERSION
        file << "version: \"" << Texts::VERSION << "\"\n";
        file << "\n";

        // WINDOW
        file << "# WINDOW\n";
        file << "window:\n";
        file << "  zoom: " << window.zoom << "\n";
        file << "  fullscreen: " << (window.fullscreen ? "true" : "false") << "\n";
        file << "\n";

        // AUDIO
        file << "# AUDIO\n";
        file << "audio:\n";
        file << "  volume: " << audio.volume << "\n";
        file << "  music:\n";
        file << "    enabled: " << (audio.music_enabled ? "true" : "false") << "\n";
        file << "    volume: " << audio.music_volume << "\n";
        file << "  sound:\n";
        file << "    enabled: " << (audio.sound_enabled ? "true" : "false") << "\n";
        file << "    volume: " << audio.sound_volume << "\n";
        file << "\n";

        // GAME
        file << "# GAME\n";
        file << "game:\n";
        file << "  habitacio_inicial: " << game.habitacio_inicial << "\n";
        file << "  piramide_inicial: " << game.piramide_inicial << "\n";
        file << "  vides: " << game.vides << "\n";

        file.close();

        std::cout << "Config file saved successfully\n\n";
        return true;
    }

}  // namespace Options
