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

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

namespace fs = std::filesystem;

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

    // sanitize the prefab 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 = '_';

    fs::path prefabDir = fs::path(ProjectManager::GetCurrentAssetsPath()) / "Prefabs";

    std::error_code ec;
    fs::create_directories(prefabDir, ec);
    if (ec)
        Logger::LogError("[Prefab] Could not create prefab directory '%s': %s",
                         prefabDir.string().c_str(), ec.message().c_str());

    fs::path fullPath = prefabDir / (filename + ".cpfb");

    YAML::Emitter objectOut;
    objectOut.SetIndent(2);
    obj->Save(objectOut);

    YAML::Node objectNode;
    try
    {
        objectNode = YAML::Load(objectOut.c_str());
    }
    catch (const YAML::Exception &e)
    {
        Logger::LogError("[Prefab] Failed to parse object YAML: %s", e.what());
        return "";
    }

    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(fullPath.string());
    out << YAML::Key << "prefabYAML" << YAML::Value << objectNode;
    out << YAML::EndMap;

    // write out the file
    std::ofstream file(fullPath);
    if (!file.is_open())
    {
        Logger::LogError("[Prefab] Failed to write prefab file: %s",
                         fullPath.string().c_str());
        return "";
    }
    file << out.c_str();
    file.close();

    Logger::LogInfo("Saved prefab to Project ");
    return fullPath.string();
}
