#include <imgui.h>
#include "../../Entitys/Object.h"
#include "../../core/utils/Profiler.h"
#include "../../core/utils/Logging.h"
#include "../../core/functions/Prefab.h"

#include "../../utils/GameObjectsList.h"

void DrawObjectNode(const std::shared_ptr<Object> &obj)
{
    if (!obj)
        return;

    PROFILE_ENGINE_SCOPE("SceneTree");

    const bool isSelected = (obj == selected);
    const bool hasChildren = !obj->GetChildren().empty();
    const char *name = obj->GetName().c_str();

    ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
                               ImGuiTreeNodeFlags_SpanAvailWidth |
                               ImGuiTreeNodeFlags_DefaultOpen |
                               (isSelected ? ImGuiTreeNodeFlags_Selected : 0) |
                               (!hasChildren ? ImGuiTreeNodeFlags_Leaf : 0);

    if (obj->IsPrefab())
        ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3f, 0.6f, 1.0f, 1.0f));

    bool open = ImGui::TreeNodeEx((void *)(intptr_t)obj->uid.id, flags, "%s", name);

    if (obj->IsPrefab())
        ImGui::PopStyleColor();

    if (ImGui::IsItemClicked())
        selected = obj;

    // --- Right-click context menu ---
    if (ImGui::BeginPopupContextItem())
    {
        if (ImGui::MenuItem("Delete"))
            pendingDeletion.push_back(obj);

        if (ImGui::MenuItem("Create Child"))
        {
            auto child = std::make_shared<Object>("NewObject");
            obj->AddChild(child);
            selected = child;
            ImGui::OpenPopup("RenameObject");
        }

        if (ImGui::MenuItem("Duplicate"))
        {
            auto clone = std::make_shared<Object>(*obj);
            if (auto parent = obj->GetParent())
                parent->AddChild(clone);
            else
                objects.push_back(clone);

            selected = clone;
            ImGui::OpenPopup("RenameObject");
        }

        if (ImGui::MenuItem("Convert to Prefab"))
        {
            std::string path = Prefab::CreatePrefab(obj);
            if (path.empty())
                Logger::LogError("Failed to create prefab.");
        }

        ImGui::EndPopup();
    }

    // --- Drag source ---
    if (ImGui::BeginDragDropSource())
    {
        ImGui::SetDragDropPayload("OBJECT", &obj, sizeof(obj));
        ImGui::Text("%s", name);
        ImGui::EndDragDropSource();
    }

    if (ImGui::BeginDragDropTarget())
    {
        if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("OBJECT"))
        {
            auto dragged = *static_cast<std::shared_ptr<Object> *>(payload->Data);
            if (dragged && dragged != obj)
            {
                bool valid = true;
                for (Object *a = obj.get(); a; a = a->GetParent())
                {
                    if (a == dragged.get())
                    {
                        valid = false;
                        break;
                    }
                }

                if (valid)
                {
                    if (auto oldP = dragged->GetParent())
                        oldP->RemoveChild(dragged.get());
                    else
                        objects.erase(std::remove(objects.begin(), objects.end(), dragged), objects.end());

                    obj->AddChild(dragged);
                    dragged->SetWorldPosition(
                        dragged->GetWorldPosition() - obj->GetWorldPosition());
                }
            }
        }
        ImGui::EndDragDropTarget();
    }

    if (open)
    {
        if (hasChildren)
        {
            for (const auto &child : obj->GetChildren())
                if (child)
                    DrawObjectNode(child);
        }
        ImGui::TreePop();
    }
}