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

namespace MajacloudSdk.Samples.Starter
{
    public sealed class CloudSavePanel : MonoBehaviour
    {
        [SerializeField] private TMP_InputField levelInput;
        [SerializeField] private TMP_InputField coinsInput;
        [SerializeField] private TMP_InputField nicknameInput;
        [SerializeField] private Button saveButton;
        [SerializeField] private Button loadButton;
        [SerializeField] private Button deleteButton;
        [SerializeField] private TMP_Text revisionLabel;
        [SerializeField] private TMP_Text statusLabel;

        private long? _lastRevision;

        private string SaveKey => StarterController.Instance != null ? StarterController.Instance.SaveKey : "progress";

        private void Awake()
        {
            if (saveButton != null) saveButton.onClick.AddListener(Save);
            if (loadButton != null) loadButton.onClick.AddListener(Load);
            if (deleteButton != null) deleteButton.onClick.AddListener(Delete);
        }

        private void OnEnable()
        {
            if (Majacloud.IsInitialized && Majacloud.Auth.IsSignedIn && _lastRevision == null) Load();
        }

        /// <summary>Called by StarterController once the player is signed in.</summary>
        public void OnSignedIn()
        {
            if (isActiveAndEnabled && _lastRevision == null) Load();
        }

        public async void Save()
        {
            if (!Majacloud.IsInitialized) return;
            var progress = new PlayerProgress
            {
                level = int.TryParse(levelInput != null ? levelInput.text : "1", NumberStyles.Integer, CultureInfo.InvariantCulture, out var level) ? level : 1,
                coins = int.TryParse(coinsInput != null ? coinsInput.text : "0", NumberStyles.Integer, CultureInfo.InvariantCulture, out var coins) ? coins : 0,
                nickname = nicknameInput != null ? nicknameInput.text : string.Empty,
            };
            SetStatus("Saving…");
            // Passing the last known revision makes the save conditional: a 409 means it changed elsewhere.
            var result = await Majacloud.CloudSave.SaveAsync(SaveKey, progress, _lastRevision);
            if (this == null) return;
            if (!result.Ok)
            {
                if (result.Error.Code == MajacloudErrorCode.RevisionMismatch)
                {
                    SetStatus("This save changed on another device. Load the latest first.");
                    StarterController.Toast("Save changed elsewhere — load first", true);
                    return;
                }
                SetStatus(result.Error.Message);
                StarterController.Toast(result.Error.Message, true);
                return;
            }
            _lastRevision = result.Value.Revision;
            if (revisionLabel != null) revisionLabel.text = "Revision: " + result.Value.Revision;
            SetStatus("Saved " + result.Value.SizeBytes + " bytes.");
            StarterController.Toast("Progress saved (revision " + result.Value.Revision + ")");
        }

        public async void Load()
        {
            if (!Majacloud.IsInitialized) return;
            SetStatus("Loading…");
            var result = await Majacloud.CloudSave.LoadAsync<PlayerProgress>(SaveKey);
            if (this == null) return;
            if (!result.Ok)
            {
                _lastRevision = result.IsNotFound ? 0 : _lastRevision;
                SetStatus(result.IsNotFound ? "No save yet. Fill the fields and press Save." : result.Error.Message);
                if (revisionLabel != null) revisionLabel.text = "Revision: –";
                return;
            }
            var data = result.Value.Data;
            if (levelInput != null) levelInput.text = data.level.ToString(CultureInfo.InvariantCulture);
            if (coinsInput != null) coinsInput.text = data.coins.ToString(CultureInfo.InvariantCulture);
            if (nicknameInput != null) nicknameInput.text = data.nickname ?? string.Empty;
            _lastRevision = result.Value.Revision;
            if (revisionLabel != null) revisionLabel.text = "Revision: " + result.Value.Revision;
            SetStatus("Loaded revision " + result.Value.Revision + ".");
        }

        public async void Delete()
        {
            if (!Majacloud.IsInitialized) return;
            var result = await Majacloud.CloudSave.DeleteAsync(SaveKey);
            if (this == null) return;
            if (!result.Ok)
            {
                SetStatus(result.Error.Message);
                return;
            }
            _lastRevision = 0;
            if (revisionLabel != null) revisionLabel.text = "Revision: –";
            SetStatus(result.Value ? "Save deleted." : "There was nothing to delete.");
        }

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