using System;
using UnityEngine;

namespace CoolGameX
{
    // Request/response shapes. Serialized with JsonUtility so strings are always
    // escaped correctly (no hand-built JSON).
    internal static class Dto
    {
        [Serializable] internal class Error { public string error; }

        [Serializable] internal class Unlock { public string gameSlug; public string achievementSlug; }
        [Serializable] internal class UnlockResponse { public bool success; public bool newlyUnlocked; }
        [Serializable] internal class AchievementList { public AchievementInfo[] achievements; }

        [Serializable] internal class StatSet { public string gameSlug; public string key; public int value; }
        [Serializable] internal class StatAdd { public string gameSlug; public string key; public int amount; }
        [Serializable] internal class StatValue { public string key; public int value; }
        [Serializable] internal class StatList { public StatEntry[] stats; }

        [Serializable] internal class Playtime { public string gameSlug; public int minutes; }

        [Serializable] internal class Submit { public string gameSlug; public string board; public long score; public string sort; public bool keepBest; public string metadata; }
        [Serializable] internal class SubmitResponse { public bool success; public bool improved; public long score; public int rank; }

        [Serializable] internal class Save { public string gameSlug; public string key; public string data; }
        [Serializable] internal class SaveResponse { public string key; public string data; public int size; public string updated_at; }
        [Serializable] internal class SaveList { public SaveSlot[] saves; }

        [Serializable] internal class Ownership { public bool owns; public string[] dlc; }
        [Serializable] internal class DlcOwned { public string[] owned; }
        [Serializable] internal class Refresh { public string token; public long expiresAt; }
        [Serializable] internal class Empty { }
    }

    internal static class Json
    {
        internal static string Of(object value) => JsonUtility.ToJson(value);

        internal static T Parse<T>(string body) where T : class
        {
            if (string.IsNullOrEmpty(body)) return null;
            try { return JsonUtility.FromJson<T>(body); }
            catch (Exception e) { Log.Warn($"Couldn't read the server response ({typeof(T).Name}): {e.Message}"); return null; }
        }

        internal static string ErrorOf(string body)
        {
            if (string.IsNullOrEmpty(body) || body[0] != '{') return null;
            try { var e = JsonUtility.FromJson<Dto.Error>(body); return string.IsNullOrEmpty(e?.error) ? null : e.error; }
            catch { return null; }
        }

        /// <summary>URL-encode a query value.</summary>
        internal static string Q(string value) => Uri.EscapeDataString(value ?? "");
    }
}
