using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UDB.UI;
using Unity.Netcode;
using Unity.Services.Authentication;
using Unity.Services.Lobbies.Models;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ServerListModule : MonoBehaviour
{
    public MatchmakingService matchmakingService;

    public UnityEvent<Lobby> OnSelectedLobby;
    public UnityEvent OnWillLoggingIn;
    public UnityEvent OnDidLoggingIn;
    public Transform listContainer;

    [SerializeField] private LobbyRoomPanel _lobbyPanelPrefab;
    [SerializeField] private GameObject _noLobbiesText;
    [SerializeField] private float _lobbyRefreshRate = 2;

    private readonly List<LobbyRoomPanel> _currentLobbySpawns = new();
    float _nextRefreshTime;
    Task task;

    void Awake()
    {
    }

    void Update()
    {
        if (Time.time >= _nextRefreshTime && (task == null || task.IsCompleted))
            task = FetchLobbies();
    }

    void OnEnable()
    {
        foreach (Transform child in listContainer) {
            //dynamicListFixer.items.Remove(child.gameObject.GetComponent<Selectable>());
            Destroy(child.gameObject);
        }
        _currentLobbySpawns.Clear();
    }

    private async Task FetchLobbies()
    {
        try {
            if (Authentication.IsLoggedIn() == false) {
                _noLobbiesText.SetActive(false);
                Debug.Log("Will log in");
                OnWillLoggingIn?.Invoke();
                await Authentication.Login();
                OnDidLoggingIn?.Invoke();
                Debug.Log("Did log in");
            }


            _nextRefreshTime = Time.time + _lobbyRefreshRate;

            // Grab all current lobbies
            var allLobbies = await matchmakingService.GatherLobbies();

            // Destroy all the current lobby panels which don't exist anymore.
            // Exclude our own homes as it'll show for a brief moment after closing the room
            var lobbyIds = allLobbies.Where(l => l.HostId != Authentication.PlayerId).Select(l => l.Id);
            var notActive = _currentLobbySpawns.Where(l => !lobbyIds.Contains(l.Lobby.Id)).ToList();

            foreach (var panel in notActive) {
                //dynamicListFixer.items.Remove(panel.gameObject.GetComponent<Selectable>());
                Destroy(panel.gameObject);
                _currentLobbySpawns.Remove(panel);
            }

            // Update or spawn the remaining active lobbies
            foreach (var lobby in allLobbies) {
                var current = _currentLobbySpawns.FirstOrDefault(p => p.Lobby.Id == lobby.Id);
                if (current != null) {
                    current.UpdateDetails(lobby);
                }
                else {
                    var panel = Instantiate(_lobbyPanelPrefab, listContainer);
                    panel.Init(lobby);
                    panel.Selected += OnLobbySelected;
                    //dynamicListFixer.items.Insert(0, panel.gameObject.GetComponent<Selectable>());
                    if (_currentLobbySpawns.Count == 0) {
                        EventSystem.current.SetSelectedGameObject(panel.gameObject);
                    }
                    _currentLobbySpawns.Add(panel);
                }
            }

            _noLobbiesText.SetActive(!_currentLobbySpawns.Any());
        }
        catch (Exception e) {
            Debug.LogError(e);
        }
    }

    void OnLobbySelected(Lobby lobby)
    {
        OnSelectedLobby.Invoke(lobby);
    }

    public void Cancel()
    {
        Debug.Log("Cancel Server List");
        NetworkManager.Singleton.Shutdown();
        if (AuthenticationService.Instance.IsSignedIn) {
            AuthenticationService.Instance.SignOut();
        }
    }
}
