using UnityEngine;
using Fusion;
using ReadyPlayerMe.Core;
using System;

public class GLBDownloader : NetworkBehaviour
{
    private GameObject currentGlbModel;
    public GameObject GetCurrentGlbModel() => currentGlbModel;

    private AvatarObjectLoader avatarLoader;
    private AvatarLoaderSettings avatarLoaderSettings;

    [Networked, OnChangedRender(nameof(OnAvatarUrlChanged))]
    private NetworkString<_512> AvatarUrl { get; set; }

    private string _previousUrl = null;

    public override void Spawned()
    {
        Debug.Log($"[GLBDownloader] Spawned for {Object.InputAuthority}, local is {Runner.LocalPlayer}");

        if (Object.HasInputAuthority)
        {
            string modelUrl = EN.instance.Me.characterUrl;
            if (!string.IsNullOrEmpty(modelUrl))
            {
                Debug.Log($"[GLBDownloader] Setting AvatarUrl to {modelUrl} for local player");
                AvatarUrl = modelUrl;
            }
            else
            {
                Debug.LogError("Character URL is empty.");
            }
        }
        else
        {
            // For late joiners: handle already set avatar URL
            if (!string.IsNullOrEmpty(AvatarUrl.ToString()))
            {
                Debug.Log($"[GLBDownloader] Late joiner loading avatar for player {Object.InputAuthority}: {AvatarUrl}");
                _previousUrl = AvatarUrl.ToString();
                LoadAvatar(_previousUrl);
            }
        }
    }

    private void OnAvatarUrlChanged()
    {
        Debug.Log($"[GLBDownloader] OnAvatarUrlChanged called on {Runner.LocalPlayer} for player {Object.InputAuthority}");

        string newUrl = AvatarUrl.ToString();
        if (!string.IsNullOrEmpty(newUrl) && newUrl != _previousUrl)
        {
            _previousUrl = newUrl;
            Debug.Log($"[GLBDownloader] Loading avatar for player {Object.InputAuthority}: {newUrl}");
            LoadAvatar(newUrl);
        }
    }

    private void LoadAvatar(string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            Debug.LogWarning("[GLBDownloader] LoadAvatar called with empty URL.");
            return;
        }

        if (avatarLoaderSettings == null)
        {
            avatarLoaderSettings = AvatarLoaderSettings.LoadSettings();
        }

        avatarLoader = new AvatarObjectLoader();
        avatarLoader.OnFailed += OnFailed;
        avatarLoader.OnCompleted += OnCompleted;

        if (avatarLoaderSettings != null)
        {
            avatarLoader.AvatarConfig = avatarLoaderSettings.AvatarConfig;
            if (avatarLoaderSettings.GLTFDeferAgent != null)
            {
                avatarLoader.GLTFDeferAgent = avatarLoaderSettings.GLTFDeferAgent;
            }
        }

        avatarLoader.LoadAvatar(url);
        Debug.Log("[GLBDownloader] Avatar download started.");
    }

    private void OnFailed(object sender, FailureEventArgs args)
    {
        Debug.LogError($"[GLBDownloader] Avatar load failed: {args.Type} - {args.Message}");
    }

    private void OnCompleted(object sender, CompletionEventArgs args)
    {
        if (args.Avatar == null)
        {
            Debug.LogError("[GLBDownloader] Avatar loading completed but avatar is null.");
            return;
        }

        currentGlbModel = args.Avatar;

        currentGlbModel.transform.position = transform.position;
        currentGlbModel.transform.rotation = transform.rotation;
        currentGlbModel.transform.localScale = Vector3.one;
        currentGlbModel.tag = "NetworkGLB";

        GameObject avatar = this.gameObject;
        if (avatar != null)
        {
            AttachToAvatarRig(avatar);
        }

        Debug.Log($"[GLBDownloader] Avatar loaded and attached for player {Object.InputAuthority}");
    }

    private void AttachToAvatarRig(GameObject avatar)
    {
        if (currentGlbModel == null) return;

        Transform avatarRig = avatar.transform.Find("1");
        if (avatarRig == null)
        {
            Debug.LogWarning("[GLBDownloader] Could not find rig root (child named '1') to attach avatar.");
            return;
        }

        IKTargetFollowVRRig ikRig = avatarRig.GetComponent<IKTargetFollowVRRig>();
        if (ikRig != null)
        {
            ikRig.head.ikTarget = currentGlbModel.transform;
        }

        currentGlbModel.transform.SetParent(avatarRig);
        currentGlbModel.transform.localPosition = new Vector3(0, 0.3f, 0);
        currentGlbModel.transform.localRotation = Quaternion.identity;
        currentGlbModel.transform.localScale = new Vector3(2,2,2);
    }

    private void OnDestroy()
    {
        if (avatarLoader != null)
        {
            avatarLoader.OnFailed -= OnFailed;
            avatarLoader.OnCompleted -= OnCompleted;
        }
    }
}
