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

namespace IGP.Multiplayer.Samples
{
    /// <summary>
    /// Hosted room lifecycle sample for developers who need to understand the end-to-end room flow.
    /// Attach this to the same GameObject as <see cref="IGPMultiplayerRuntime"/>.
    /// </summary>
    public sealed class IGPRoomLifecycleSample : MonoBehaviour
    {
        [Header("References")]
        [SerializeField] private IGPMultiplayerRuntime? runtimeManager = null;

        [Header("Room Actions")]
        [SerializeField] private string targetTeamId = "team-a";
        [SerializeField] private bool autoRefreshOnJoin = true;

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

        private void OnEnable()
        {
            if (runtimeManager == null)
            {
                Debug.LogWarning("[IGP RoomLifecycle] IGPMultiplayerRuntime not found.");
                return;
            }

            runtimeManager.ConnectionChanged += HandleConnectionChanged;
            runtimeManager.RoomChanged += HandleRoomChanged;
            runtimeManager.ErrorOccurred += HandleRuntimeError;

        }

        private void OnDisable()
        {
            if (runtimeManager != null)
            {
                runtimeManager.ConnectionChanged -= HandleConnectionChanged;
                runtimeManager.RoomChanged -= HandleRoomChanged;
                runtimeManager.ErrorOccurred -= HandleRuntimeError;
            }
        }

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

            try
            {
                await runtimeManager.RefreshHostedRoomAsync();
                Debug.Log("[IGP RoomLifecycle] RefreshHostedRoomAsync completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] RefreshRoom failed: {ex.Message}");
            }
        }

        public async void SetSceneGate(string value = "arena-ready")
        {
            if (runtimeManager == null)
            {
                return;
            }

            try
            {
                await runtimeManager.SetSceneGateAsync(value);
                Debug.Log($"[IGP RoomLifecycle] SetSceneGateAsync(`{value}`) completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] SetSceneGate failed: {ex.Message}");
            }
        }

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

            try
            {
                await runtimeManager.StartHostedGameAsync();
                Debug.Log("[IGP RoomLifecycle] StartHostedGameAsync completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] StartGame failed: {ex.Message}");
            }
        }

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

            try
            {
                await runtimeManager.FinishHostedGameAsync();
                Debug.Log("[IGP RoomLifecycle] FinishHostedGameAsync completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] FinishGame failed: {ex.Message}");
            }
        }

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

            try
            {
                await runtimeManager.RequestRematchAsync();
                Debug.Log("[IGP RoomLifecycle] RequestRematchAsync completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] RequestRematch failed: {ex.Message}");
            }
        }

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

            try
            {
                await runtimeManager.LeaveHostedRoomAsync();
                Debug.Log("[IGP RoomLifecycle] LeaveHostedRoomAsync completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] LeaveRoom failed: {ex.Message}");
            }
        }

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

            try
            {
                await runtimeManager.ChangeHostedTeamAsync(targetTeamId);
                Debug.Log($"[IGP RoomLifecycle] ChangeHostedTeamAsync({targetTeamId}) completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] ChangeTeam failed: {ex.Message}");
            }
        }

        private async void HandleRoomChanged(IGPRoomChangedEvent change)
        {
            var room = change.Room ?? change.PreviousRoom;
            Debug.Log($"[IGP RoomLifecycle] Room changed: kind={change.Kind}, id={room?.id}, flags={change.Changes}");

            if (change.Kind != IGPRoomChangeKind.Joined || !autoRefreshOnJoin || runtimeManager == null)
            {
                return;
            }

            try
            {
                await runtimeManager.RefreshHostedRoomAsync();
                Debug.Log("[IGP RoomLifecycle] Auto refresh after join completed.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"[IGP RoomLifecycle] Auto refresh failed: {ex.Message}");
            }
        }

        private void HandleConnectionChanged(IGPMultiplayerConnectionChangedEvent change)
        {
            Debug.Log($"[IGP RoomLifecycle] Connection changed: state={change.State}, ready={change.IsReady}");
        }

        private void HandleRuntimeError(IGPMultiplayerErrorEvent error)
        {
            Debug.LogError($"[IGP RoomLifecycle] Runtime error: {error}");
        }
    }
}
