using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

/// <summary>
/// 에디터/PC 환경 전용 테스트 보조 스크립트.
/// RuntimeInitializeOnLoadMethod로 자동 생성되므로 씬에 직접 추가할 필요 없습니다.
/// Quest 빌드 시 자동으로 비활성화됩니다.
///
/// 기능:
///   1. TrackedDeviceGraphicRaycaster → GraphicRaycaster 교체 (마우스 클릭 활성화)
///   2. Canvas EventCamera 자동 갱신 (클릭 위치 정확도)
///   3. ESC 키로 씬별 뒤로가기
/// </summary>
public class DesktopUIMode : MonoBehaviour
{
#if !UNITY_ANDROID || UNITY_EDITOR

    // 어떤 씬에서 Play를 눌러도 자동 실행
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    private static void AutoCreate()
    {
        if (FindObjectOfType<DesktopUIMode>() != null) return; // 이미 있으면 생성 안 함

        var go = new GameObject("[DesktopUIMode]");
        go.AddComponent<DesktopUIMode>();
    }

    // ESC 뒤로가기 씬 매핑
    private static readonly System.Collections.Generic.Dictionary<string, string> BackSceneMap =
        new System.Collections.Generic.Dictionary<string, string>
        {
            { "SongSelect",     "Intro"       },
            { "SongCreator",    "Intro"       },
            { "MapEditorScene", "SongCreator" },
            { "Game",           "SongSelect"  },
        };

    private void Awake()
    {
        // 중복 방지 (씬에 직접 놓은 경우 AutoCreate와 겹칠 수 있음)
        if (FindObjectsOfType<DesktopUIMode>().Length > 1)
        {
            Destroy(gameObject);
            return;
        }

        DontDestroyOnLoad(gameObject);
        SceneManager.sceneLoaded += OnSceneLoaded;
        PatchCanvases(); // 현재 씬 즉시 패치
    }

    private void OnDestroy()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        StartCoroutine(PatchAfterFrame());
    }

    private System.Collections.IEnumerator PatchAfterFrame()
    {
        yield return null; // Canvas.Awake 이후 실행 보장
        PatchCanvases();
    }

    private void Update()
    {
        RefreshCanvasCameras(); // 매 프레임 worldCamera 갱신 (카메라 초기화 타이밍 보정)

        if (Keyboard.current?.escapeKey.wasPressedThisFrame == true)
            GoBack();
    }

    // ── Canvas 패치 ──────────────────────────────────────────

    private static void PatchCanvases()
    {
        foreach (var canvas in FindObjectsOfType<Canvas>())
        {
            if (canvas.renderMode != RenderMode.WorldSpace) continue;

            // TrackedDeviceGraphicRaycaster → GraphicRaycaster
            var tracked = canvas.GetComponent("TrackedDeviceGraphicRaycaster");
            if (tracked != null)
            {
                DestroyImmediate(tracked);
                if (canvas.GetComponent<GraphicRaycaster>() == null)
                    canvas.gameObject.AddComponent<GraphicRaycaster>();

                Debug.Log($"[DesktopUIMode] {canvas.name} Raycaster 교체 완료");
            }
        }

        RemoveDuplicateAudioListeners();
        RefreshCanvasCameras();
    }

    private static void RemoveDuplicateAudioListeners()
    {
        var listeners = FindObjectsOfType<AudioListener>();
        if (listeners.Length <= 1) return;

        // 첫 번째(DontDestroyOnLoad에 없는 것 우선)만 남기고 나머지 제거
        AudioListener keep = null;
        foreach (var al in listeners)
        {
            if (al.gameObject.scene.name != "DontDestroyOnLoad")
            { keep = al; break; }
        }
        if (keep == null) keep = listeners[0];

        foreach (var al in listeners)
        {
            if (al != keep)
            {
                Debug.Log($"[DesktopUIMode] 중복 AudioListener 제거: {al.gameObject.name}");
                DestroyImmediate(al);
            }
        }
    }

    private static void RefreshCanvasCameras()
    {
        Camera cam = Camera.main;
        if (cam == null)
        {
            // Camera.main이 없으면 씬에서 직접 찾기 (DontDestroyOnLoad 제외)
            foreach (var c in FindObjectsOfType<Camera>())
            {
                if (c.enabled && c.gameObject.scene.name != "DontDestroyOnLoad")
                {
                    cam = c;
                    break;
                }
            }
        }
        if (cam == null) cam = FindObjectOfType<Camera>(); // 최후 수단
        if (cam == null) return;

        foreach (var canvas in FindObjectsOfType<Canvas>())
        {
            if (canvas.renderMode == RenderMode.WorldSpace && canvas.worldCamera != cam)
                canvas.worldCamera = cam;
        }
    }

    // ── ESC 뒤로가기 ─────────────────────────────────────────

    private static void GoBack()
    {
        string current = SceneManager.GetActiveScene().name;
        if (BackSceneMap.TryGetValue(current, out string target))
            SceneManager.LoadScene(target);
    }

#endif
}
