using System.Threading.Tasks;
using UnityEngine;

namespace CoolGameX
{
    /// <summary>
    /// Playtime tracking. With the default settings the launcher times games it
    /// starts, and the SDK only tracks when the game runs on its own — so minutes
    /// are never counted twice. Call these yourself only for custom setups.
    /// </summary>
    public class Playtime
    {
        private float sessionStart = -1f;
        private float reportedUntil = -1f;

        /// <summary>True between <see cref="StartSession"/> and <see cref="EndSession"/>.</summary>
        public bool IsActive { get; private set; }

        /// <summary>Begins a playtime session.</summary>
        public void StartSession()
        {
            sessionStart = reportedUntil = Time.realtimeSinceStartup;
            IsActive = true;
            Log.Verbose("Playtime session started.");
        }

        /// <summary>Ends the session and reports the minutes not yet reported.</summary>
        public async Task<int> EndSession()
        {
            if (!IsActive) return 0;
            int minutes = TakeMinutes(round: true);
            IsActive = false;
            if (minutes > 0) await ReportMinutes(minutes);
            Log.Verbose($"Playtime session ended ({minutes} min).");
            return minutes;
        }

        /// <summary>Report minutes directly. Queued while offline.</summary>
        public async Task<bool> ReportMinutes(int minutes)
        {
            if (minutes <= 0) return true;
            var res = await Net.PostJson("/api/playtime/update", Json.Of(new Dto.Playtime { gameSlug = CoolAPI.GameSlug, minutes = minutes }), auth: true, retry: false);
            if (res.Success) return true;
            if (res.IsNetworkError && CoolAPI.Queue.Enabled)
            {
                CoolAPI.Queue.Enqueue(new OfflineQueue.Op { type = "playtime", value = minutes });
                return true;
            }
            return false;
        }

        /// <summary>Whole minutes played since the last report (the remainder carries over).</summary>
        internal int TakeMinutes(bool round)
        {
            if (!IsActive) return 0;
            float now = Time.realtimeSinceStartup;
            float minutes = (now - reportedUntil) / 60f;
            int whole = round ? Mathf.RoundToInt(minutes) : Mathf.FloorToInt(minutes);
            if (whole <= 0) return 0;
            reportedUntil = round ? now : reportedUntil + whole * 60f;
            return whole;
        }

        /// <summary>
        /// On quit there's no time for a request, so the unreported minutes are saved
        /// to the offline queue and sent on the next launch.
        /// </summary>
        internal void QueueRemainder()
        {
            if (!IsActive) return;
            int minutes = TakeMinutes(round: true);
            IsActive = false;
            if (minutes > 0 && CoolAPI.Queue != null) CoolAPI.Queue.Enqueue(new OfflineQueue.Op { type = "playtime", value = minutes });
        }
    }
}
