#include "Prefab.h"
#include "../utils/Logging.h"
#include "../utils/utils.h"
#include "../../Entitys/Object.h"
#include "../../core/utils/AssetManager.h"

#include <yaml-cpp/yaml.h>
#include <fstream>
#include <filesystem>
#include <cctype>
#include <ctime>
#include <sstream>


std::string Prefab::CreatePrefab(const std::shared_ptr<Object>& obj)
{
    if (!obj)
        return "";

    // Clean filename
    std::string filename = obj->GetName().empty() ? "Unnamed" : obj->GetName();
    for (auto& ch : filename)
        if (ch == '/' || ch == '\\' || ch == ':' || ch == '*' || ch == '?' || ch == '\"' || ch == '<' || ch == '>' || ch == '|')
            ch = '_';

    std::string path = "C:/Users/spenc/OneDrive/Desktop/" + filename + ".cpfb";

    // Serialize Object to string
    YAML::Emitter objectOut;
    objectOut.SetIndent(2);
    obj->Save(objectOut);

    // Parse the object YAML string back into a real node
    YAML::Node objectNode;
    try {
        objectNode = YAML::Load(objectOut.c_str());
    } catch (const YAML::Exception& e) {
        Logger::LogError("[Prefab] Failed to parse object YAML for prefab: %s", e.what());
        return "";
    }

    // Write the outer asset structure
    YAML::Emitter out;
    out.SetIndent(2);
    out << YAML::BeginMap;

    out << YAML::Key << "uaid" << YAML::Value << AssetManager::GenerateUAID();
    out << YAML::Key << "filename" << YAML::Value << filename + ".cpfb";
    out << YAML::Key << "filetype" << YAML::Value << "cpfb";
    out << YAML::Key << "type" << YAML::Value << "Prefab";
    out << YAML::Key << "prefabName" << YAML::Value << obj->GetName();
    out << YAML::Key << "hash" << YAML::Value << "";
    out << YAML::Key << "lastModified" << YAML::Value << GetFileLastWrite(path);
    out << YAML::Key << "prefabYAML" << YAML::Value << objectNode;

    out << YAML::EndMap;

    std::ofstream file(path);
    if (file.is_open())
    {
        file << out.c_str();
        file.close();
        Logger::LogInfo("[Prefab] Saved prefab: %s", path.c_str());
    }
    else
    {
        Logger::LogError("[Prefab] Failed to write prefab file: %s (%s)", path.c_str(), std::strerror(errno));
    }

    return path;
}

