using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;

public class FindMissingReferencesInScenes 
{

    [MenuItem("Tool/Find Missing References In All Scenes")]
    static void FindMissingReferencesInScene()
    {
        string[] scenePaths = GetAllPathsByType("Scene");

        foreach (string scenePath in scenePaths)
        {
            EditorSceneManager.OpenScene(scenePath);
            Debug.Log($"Searching for missing references in scene: {scenePath}");

            GameObject[] rootObjects = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();

            foreach (GameObject rootObject in rootObjects)
            {
                FindMissingReferencesInGameObject(rootObject);
            }
        }

        Debug.Log("Finished searching for missing references in all scenes.");
    }

    [MenuItem("Tool/Find Missing References In All Prefab")]
    static void FindMissingReferencesInPrefab()
    {
        string[] prefabPaths = GetAllPathsByType("Prefab");

        foreach (string prefabPath in prefabPaths)
        {
            Debug.Log($"Searching for missing references in prefab: {prefabPath}");
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);

            if (prefab != null)
            {
                FindMissingReferencesInGameObject(prefab);
            }

        }
    }

    static void FindMissingReferencesInGameObject(GameObject gameObject)
    {
        Component[] components = gameObject.GetComponentsInChildren<Component>(true);

        foreach (Component component in components)
        {
            if (!component)
            {
                Debug.LogError($"Missing component found in GameObject '{gameObject.name}'");
                continue;
            }

            SerializedObject serializedObject = new SerializedObject(component);
            SerializedProperty property = serializedObject.GetIterator();

            while (property.NextVisible(true))
            {
                if (property.propertyType == SerializedPropertyType.ObjectReference 
                    && property.objectReferenceValue == null
                    && property.objectReferenceInstanceIDValue != 0)
                {
                    Debug.LogWarning($"Missing reference found in {component.GetType().Name} of GameObject '{component.gameObject.name}': {property.displayName}");
                }
            }
        }
    }

    static string[] GetAllPathsByType(string type)
    {
        string[] guids = AssetDatabase.FindAssets($"t:{type}");
        string[] typePaths = new string[guids.Length];

        for (int i = 0; i < guids.Length; i++)
        {
            typePaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
        }

        return typePaths;
    }
}