using System;
using System.Globalization;
using System.Threading.Tasks;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace MajacloudSdk.Samples.Starter
{
    /// <summary>Reusable leaderboard list. Drag the prefab into any canvas, set the slug, done.</summary>
    public sealed class LeaderboardView : MonoBehaviour
    {
        [SerializeField] private string slug = "coins";
        [SerializeField] private int limit = 10;
        [SerializeField] private bool loadOnEnable = true;
        [SerializeField] private TMP_Text titleLabel;
        [SerializeField] private TMP_Text slugLabel;
        [SerializeField] private Button refreshButton;
        [SerializeField] private Transform content;
        [SerializeField] private LeaderboardRowView rowPrefab;
        [SerializeField] private TMP_Text myRankLabel;
        [SerializeField] private TMP_Text statusLabel;

        private bool _loading;

        public string Slug
        {
            get => slug;
            set => slug = value;
        }

        public event Action<MajacloudLeaderboardPage> Loaded;

        private void Awake()
        {
            if (refreshButton != null) refreshButton.onClick.AddListener(Refresh);
            if (StarterController.Instance != null && !string.IsNullOrEmpty(StarterController.Instance.LeaderboardSlug)) slug = StarterController.Instance.LeaderboardSlug;
            if (slugLabel != null) slugLabel.text = slug;
        }

        private void OnEnable()
        {
            if (loadOnEnable) Refresh();
        }

        public void Refresh() => RefreshAsync().Forget();

        public async Task RefreshAsync()
        {
            if (_loading || !Majacloud.IsInitialized) return;
            _loading = true;
            SetStatus("Loading…");
            var page = await Majacloud.Leaderboards.GetTopAsync(slug, limit);
            if (this == null) return;
            _loading = false;
            if (!page.Ok)
            {
                SetStatus(page.Error.Message);
                return;
            }
            Render(page.Value);
            Loaded?.Invoke(page.Value);
            if (Majacloud.Auth.IsSignedIn)
            {
                var rank = await Majacloud.Leaderboards.GetMyRankAsync(slug);
                if (this == null) return;
                if (myRankLabel != null)
                {
                    myRankLabel.text = rank.Ok && rank.Value.IsRanked
                        ? "Your rank #" + rank.Value.Rank + " · " + rank.Value.Score.GetValueOrDefault().ToString("#,0.##", CultureInfo.InvariantCulture)
                        : rank.Ok ? "You have no score yet" : rank.Error.Message;
                }
            }
        }

        private void Render(MajacloudLeaderboardPage page)
        {
            if (content == null || rowPrefab == null) return;
            for (int i = content.childCount - 1; i >= 0; i--) Destroy(content.GetChild(i).gameObject);
            foreach (var entry in page.Entries)
            {
                var row = Instantiate(rowPrefab, content);
                row.Bind(entry);
            }
            if (titleLabel != null && page.Leaderboard != null && !string.IsNullOrEmpty(page.Leaderboard.Name)) titleLabel.text = page.Leaderboard.Name;
            var period = page.Period != null && page.Period.EndsAt.HasValue ? " · resets " + page.Period.EndsAt.Value.ToLocalTime().ToString("MMM d HH:mm", CultureInfo.InvariantCulture) : string.Empty;
            SetStatus(page.Entries.Count == 0 ? "No scores yet. Submit one!" : page.Total + " player" + (page.Total == 1 ? string.Empty : "s") + period + (page.MaxEntries.HasValue ? " · top " + page.MaxEntries.Value + " shown on this plan" : string.Empty));
        }

        private void SetStatus(string text)
        {
            if (statusLabel != null) statusLabel.text = text;
        }
    }
}
