#include "DeletePrimCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/sdf/copyUtils.h>
#include <pxr/usd/sdf/primSpec.h>

namespace UsdLayerManager {

DeletePrimCommand::DeletePrimCommand(pxr::UsdStageRefPtr stage,
                                     const pxr::SdfPath& primPath)
    : m_stage(stage)
    , m_primPath(primPath)
    , m_description("Delete " + primPath.GetString())
{
    if (!stage) return;
    pxr::SdfLayerHandle rootLayer = stage->GetRootLayer();
    if (!rootLayer) return;

    // Only capture if the spec exists on the root layer.
    if (!rootLayer->HasSpec(primPath)) {
        LOG_ERROR("DeletePrimCommand: no spec found for " + primPath.GetString());
        return;
    }

    m_savedLayer = pxr::SdfLayer::CreateAnonymous(".usda");
    if (!m_savedLayer) return;

    // Ensure the parent path hierarchy exists in the saved layer.
    pxr::SdfPath parentPath = primPath.GetParentPath();
    while (!parentPath.IsAbsoluteRootPath() && !m_savedLayer->HasSpec(parentPath)) {
        pxr::SdfPrimSpec::New(m_savedLayer,
                              parentPath.GetName(),
                              pxr::SdfSpecifierOver);
        parentPath = parentPath.GetParentPath();
    }

    if (pxr::SdfCopySpec(rootLayer, primPath, m_savedLayer, primPath)) {
        m_specWasSaved = true;
    } else {
        LOG_ERROR("DeletePrimCommand: SdfCopySpec failed for " + primPath.GetString());
    }
}

void DeletePrimCommand::Execute() {
    if (!m_stage) return;
    try {
        if (!m_stage->RemovePrim(m_primPath))
            LOG_ERROR("DeletePrimCommand: RemovePrim failed for " + m_primPath.GetString());
    } catch (const std::exception& e) {
        LOG_ERROR(std::string("DeletePrimCommand::Execute error: ") + e.what());
    }
}

void DeletePrimCommand::Undo() {
    if (!m_stage || !m_specWasSaved || !m_savedLayer) {
        LOG_ERROR("DeletePrimCommand::Undo: cannot restore — spec was not saved");
        return;
    }
    pxr::SdfLayerHandle rootLayer = m_stage->GetRootLayer();
    if (!rootLayer) return;

    try {
        // The destination ancestors may be gone by now (e.g. the parent
        // material was itself deleted after this command ran) — SdfCopySpec
        // fails with "No spec ... when trying to set field 'primChildren'"
        // when the parent spec is missing, so recreate the chain first.
        pxr::SdfPath parentPath = m_primPath.GetParentPath();
        if (!parentPath.IsAbsoluteRootPath() && !rootLayer->GetPrimAtPath(parentPath))
            pxr::SdfCreatePrimInLayer(rootLayer, parentPath);

        if (!pxr::SdfCopySpec(m_savedLayer, m_primPath, rootLayer, m_primPath))
            LOG_ERROR("DeletePrimCommand::Undo: SdfCopySpec failed for " + m_primPath.GetString());
    } catch (const std::exception& e) {
        LOG_ERROR(std::string("DeletePrimCommand::Undo error: ") + e.what());
    }
}

} // namespace UsdLayerManager
