#nullable enable
using System;
using UnityEngine;
using IGP.UnitySDK.Models;

namespace IGP.UnitySDK.Samples
{
    /// <summary>
    /// Minimal sample MonoBehaviour for a hosted game launched by the Curio desktop client.
    /// Attach this next to <see cref="IGPRuntimeManager"/> to verify the multiplayer + achievement flow.
    /// </summary>
    public sealed class IGPHostedQuickstart : MonoBehaviour
    {
        [Header("References")]
        [SerializeField] private IGPRuntimeManager? runtimeManager = null;

        [Header("Sample Message")]
        [SerializeField] private string debugMessageType = "sample_debug";
        [SerializeField] private string debugText = "hello from igp-sdk";

        [Header("Achievement Sample")]
        [SerializeField] private string unlockAchievementKey = "first_session";
        [SerializeField] private string progressAchievementKey = "matches_played";
        [SerializeField] private double progressValue = 1d;
        [SerializeField] private string progressSourceKey = "sample_match_complete";

        [Header("Auto Actions")]
        [SerializeField] private bool initializeOnStart = true;
        [SerializeField] private bool setReadyOnRoomJoin = true;

        private void Awake()
        {
            runtimeManager ??= FindObjectOfType<IGPRuntimeManager>();
        }

        private void OnEnable()
        {
            if (runtimeManager == null)
            {
                Debug.LogWarning("[IGP Sample] IGPRuntimeManager not found. Add it to the scene first.");
                return;
            }

            runtimeManager.onConnectionStateChanged.AddListener(HandleConnectionStateChanged);
            runtimeManager.onRoomJoined.AddListener(HandleRoomJoined);
            runtimeManager.onMessageReceived.AddListener(HandleMessageReceived);
            runtimeManager.onError.AddListener(HandleError);
        }

        private void OnDisable()
        {
            if (runtimeManager == null)
            {
                return;
            }

            runtimeManager.onConnectionStateChanged.RemoveListener(HandleConnectionStateChanged);
            runtimeManager.onRoomJoined.RemoveListener(HandleRoomJoined);
            runtimeManager.onMessageReceived.RemoveListener(HandleMessageReceived);
            runtimeManager.onError.RemoveListener(HandleError);
        }

        private async void Start()
        {
            if (!initializeOnStart || runtimeManager == null)
            {
                return;
            }

            var initialized = await runtimeManager.InitializeAsync();
            if (!initialized)
            {
                Debug.LogError("[IGP Sample] SDK initialization failed.");
            }
        }

        public async void SendSampleMessage()
        {
            if (runtimeManager == null)
            {
                Debug.LogWarning("[IGP Sample] runtimeManager is missing.");
                return;
            }

            try
            {
                await runtimeManager.SendMessageAsync(new Message
                {
                    type = debugMessageType,
                    roomId = runtimeManager.CurrentRoomId,
                    playerId = runtimeManager.PlayerId,
                    reliable = true,
                    content = new
                    {
                        text = debugText,
                        sentAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                    }
                });

                Debug.Log($"[IGP Sample] Sent message `{debugMessageType}`.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] SendSampleMessage failed: {ex.Message}");
            }
        }

        public async void SetReady()
        {
            if (runtimeManager == null)
            {
                return;
            }

            try
            {
                await runtimeManager.SetReadyAsync(true);
                Debug.Log("[IGP Sample] Local player marked ready.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] SetReady failed: {ex.Message}");
            }
        }

        public async void UnlockSampleAchievement()
        {
            if (runtimeManager == null)
            {
                return;
            }

            try
            {
                var result = await IGPSDK.UnlockAchievementAsync(runtimeManager, unlockAchievementKey);
                Debug.Log($"[IGP Sample] UnlockAchievement success={result.success}, duplicated={result.duplicated}, message={result.message}");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] UnlockSampleAchievement failed: {ex.Message}");
            }
        }

        public async void ReportSampleAchievementProgress()
        {
            if (runtimeManager == null)
            {
                return;
            }

            try
            {
                var result = await IGPSDK.ReportAchievementProgressAsync(
                    runtimeManager,
                    progressAchievementKey,
                    progressValue,
                    progressSourceKey);

                Debug.Log($"[IGP Sample] ReportAchievementProgress success={result.success}, duplicated={result.duplicated}, message={result.message}");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] ReportSampleAchievementProgress failed: {ex.Message}");
            }
        }

        public async void SetGlobalSampleState()
        {
            if (runtimeManager == null)
            {
                return;
            }

            try
            {
                await runtimeManager.SetGlobalStateAsync("sample:lastMessageAt", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
                Debug.Log("[IGP Sample] Updated global sample state.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] SetGlobalSampleState failed: {ex.Message}");
            }
        }

        public async void CallSampleRpc()
        {
            if (runtimeManager == null)
            {
                return;
            }

            try
            {
                var requestId = await runtimeManager.CallRPCAsync(
                    "sample_echo",
                    new
                    {
                        text = debugText,
                        sentAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                    });

                Debug.Log($"[IGP Sample] RPC dispatched with requestId={requestId}");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] CallSampleRpc failed: {ex.Message}");
            }
        }

        private async void HandleRoomJoined(Room room)
        {
            Debug.Log($"[IGP Sample] Joined room id={room.id}, code={room.code}, host={room.hostId}");

            if (!setReadyOnRoomJoin || runtimeManager == null)
            {
                return;
            }

            try
            {
                await runtimeManager.SetReadyAsync(true);
                Debug.Log("[IGP Sample] Auto-ready completed after room join.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP Sample] Auto-ready failed: {ex.Message}");
            }
        }

        private void HandleConnectionStateChanged(bool connected)
        {
            Debug.Log($"[IGP Sample] Connection changed: connected={connected}");
        }

        private void HandleMessageReceived(string messageType, object? content)
        {
            var payloadJson = content != null ? Newtonsoft.Json.JsonConvert.SerializeObject(content) : "<null>";
            Debug.Log($"[IGP Sample] Message received type={messageType}, payload={payloadJson}");
        }

        private void HandleError(string error)
        {
            Debug.LogError($"[IGP Sample] Runtime error: {error}");
        }
    }
}
