using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

namespace CoolGameX
{
    /// <summary>
    /// On-screen SDK panel (default key F8): connection, session, offline queue,
    /// one-click test unlocks and the recent SDK log. Added automatically in the
    /// Editor and development builds — see the settings asset.
    /// Uses IMGUI, so it works with both the old and the new Input System.
    /// </summary>
    [AddComponentMenu("")]
    public class CoolGameXDebugOverlay : MonoBehaviour
    {
        public KeyCode toggleKey = KeyCode.F8;

        private bool open;
        private Vector2 achScroll, logScroll;
        private AchievementInfo[] achievements = Array.Empty<AchievementInfo>();
        private bool busy;

        private void OnGUI()
        {
            var e = Event.current;
            if (e.type == EventType.KeyDown && e.keyCode == toggleKey)
            {
                open = !open;
                if (open) _ = Reload();
                e.Use();
            }
            if (!open) return;

            Ui.Ensure();
            float w = 420f, h = Mathf.Min(Screen.height - 24f, 680f);
            GUILayout.BeginArea(new Rect(12f, 12f, w, h), Ui.Panel);

            GUILayout.BeginHorizontal();
            GUILayout.Label("COOL GAMEX", Ui.Brand);
            GUILayout.Label($"SDK {CoolAPI.Version}", Ui.Dim);
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Close", Ui.Button, GUILayout.Width(56))) open = false;
            GUILayout.EndHorizontal();
            GUILayout.Label($"Press {toggleKey} to toggle this panel", Ui.Dim);
            GUILayout.Space(8);

            Row("Game", CoolAPI.GameSlug ?? "—");
            Row("Server", CoolAPI.ServerUrl ?? "—");
            Row("Connection", CoolAPI.IsConnected ? "Online" : "Offline", CoolAPI.IsConnected ? Ui.Good : Ui.Bad);
            Row("Player", CoolAPI.IsAuthenticated ? CoolAPI.Player.Name : "Not signed in", CoolAPI.IsAuthenticated ? Ui.Good : Ui.Bad);
            Row("Session", Session());
            Row("Started by launcher", CoolAPI.LaunchedFromLauncher ? "Yes" : "No");
            Row("Waiting to sync", (CoolAPI.Queue?.PendingCount ?? 0).ToString());
            if (!string.IsNullOrEmpty(CoolAPI.LastError)) Row("Last error", CoolAPI.LastError, Ui.Bad);

            GUILayout.Space(6);
            GUI.enabled = !busy && CoolAPI.IsInitialized;
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Reconnect", Ui.Button)) _ = Run(async () => { await CoolAPI.CheckConnection(); });
            if (GUILayout.Button("Sync queue", Ui.Button)) _ = Run(async () => { await CoolAPI.Queue.Flush(); });
            if (GUILayout.Button("Refresh session", Ui.Button)) _ = Run(async () => { await CoolAPI.Auth.Refresh(); });
            GUILayout.EndHorizontal();
            GUI.enabled = true;

            GUILayout.Space(10);
            GUILayout.BeginHorizontal();
            GUILayout.Label($"ACHIEVEMENTS  ({Count()} / {achievements.Length})", Ui.Section);
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Reload", Ui.Small, GUILayout.Width(56))) _ = Reload();
            GUILayout.EndHorizontal();

            achScroll = GUILayout.BeginScrollView(achScroll, GUILayout.Height(Mathf.Max(90f, h * 0.36f)));
            if (achievements.Length == 0) GUILayout.Label(CoolAPI.IsAuthenticated ? "No achievements for this game yet." : "Sign in to see achievements.", Ui.Dim);
            foreach (var a in achievements)
            {
                GUILayout.BeginHorizontal(Ui.Row);
                GUILayout.Label(a.unlocked ? "●" : "○", a.unlocked ? Ui.Good : Ui.Dim, GUILayout.Width(14));
                GUILayout.Label($"{a.name}  <color=#8d8d98>{a.slug} · {a.points} pts</color>", Ui.Text);
                GUILayout.FlexibleSpace();
                GUI.enabled = !a.unlocked && !busy && CoolAPI.IsAuthenticated;
                if (GUILayout.Button(a.unlocked ? "Unlocked" : "Unlock", Ui.Small, GUILayout.Width(70)))
                {
                    string slug = a.slug;
                    _ = Run(async () => { await CoolAPI.Achievements.UnlockDetailed(slug); achievements = await CoolAPI.Achievements.GetAll(); });
                }
                GUI.enabled = true;
                GUILayout.EndHorizontal();
            }
            GUILayout.EndScrollView();

            GUILayout.Space(6);
            GUILayout.Label("RECENT", Ui.Section);
            logScroll = GUILayout.BeginScrollView(logScroll);
            var lines = Log.Recent;
            for (int i = lines.Length - 1; i >= 0 && i >= lines.Length - 20; i--) GUILayout.Label(lines[i], Ui.Mono);
            GUILayout.EndScrollView();

            GUILayout.EndArea();
        }

        private static string Session()
        {
            var auth = CoolAPI.Auth;
            if (auth == null || !CoolAPI.IsAuthenticated) return "—";
            string kind = auth.IsGameToken ? "Game token" : "Account token";
            var left = auth.TimeLeft;
            if (!left.HasValue) return kind;
            if (left.Value.TotalSeconds <= 0) return kind + " · expired";
            return $"{kind} · {(int)left.Value.TotalHours}h {left.Value.Minutes}m left";
        }

        private int Count()
        {
            int n = 0;
            foreach (var a in achievements) if (a.unlocked) n++;
            return n;
        }

        private async Task Reload()
        {
            if (!CoolAPI.IsInitialized) return;
            await Run(async () => { achievements = await CoolAPI.Achievements.GetAll(refresh: true); });
        }

        private async Task Run(Func<Task> action)
        {
            busy = true;
            try { await action(); }
            catch (Exception ex) { Debug.LogException(ex); }
            finally { busy = false; }
        }

        private static void Row(string label, string value, GUIStyle valueStyle = null)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label(label, Ui.Dim, GUILayout.Width(140));
            GUILayout.Label(value, valueStyle ?? Ui.Text);
            GUILayout.EndHorizontal();
        }
    }

    /// <summary>
    /// The SDK's own "Achievement unlocked" toasts, for when the launcher's popup
    /// isn't there (e.g. in the Editor). Controlled by the settings asset.
    /// </summary>
    [AddComponentMenu("")]
    public class CoolGameXToasts : MonoBehaviour
    {
        private class Toast { public string title; public string sub; public float start; }

        private const float Life = 4.5f;
        private readonly List<Toast> items = new List<Toast>();

        private void OnEnable() { if (CoolAPI.Achievements != null) CoolAPI.Achievements.Unlocked += Show; }
        private void OnDisable() { if (CoolAPI.Achievements != null) CoolAPI.Achievements.Unlocked -= Show; }

        private void Show(AchievementInfo a)
        {
            items.Add(new Toast
            {
                title = string.IsNullOrEmpty(a.name) ? a.slug : a.name,
                sub = a.points > 0 ? $"+{a.points} points" : "Achievement unlocked",
                start = Time.unscaledTime,
            });
            if (items.Count > 3) items.RemoveAt(0);
        }

        private void OnGUI()
        {
            items.RemoveAll(t => Time.unscaledTime - t.start > Life);
            if (items.Count == 0) return;
            Ui.Ensure();

            const float w = 300f, h = 64f, margin = 16f;
            for (int i = 0; i < items.Count; i++)
            {
                var t = items[i];
                float age = Time.unscaledTime - t.start;
                float k = Mathf.Min(Mathf.Clamp01(age / 0.25f), Mathf.Clamp01((Life - age) / 0.3f));
                k = 1f - Mathf.Pow(1f - k, 3f);
                var r = new Rect(Screen.width - (w + margin) * k, margin + i * (h + 8f), w, h);

                GUI.Box(r, GUIContent.none, Ui.Panel);
                GUI.DrawTexture(new Rect(r.x, r.y, 3f, r.height), Ui.Accent);
                GUI.Label(new Rect(r.x + 16f, r.y + 10f, w - 24f, 16f), "ACHIEVEMENT UNLOCKED", Ui.Kicker);
                GUI.Label(new Rect(r.x + 16f, r.y + 26f, w - 24f, 20f), t.title, Ui.Title);
                GUI.Label(new Rect(r.x + 16f, r.y + 44f, w - 24f, 16f), t.sub, Ui.Gold);
            }
        }
    }

    /// <summary>Shared IMGUI styles for the SDK's on-screen tools.</summary>
    internal static class Ui
    {
        internal static GUIStyle Panel, Brand, Dim, Text, Good, Bad, Section, Button, Small, Row, Mono, Kicker, Title, Gold;
        internal static Texture2D Accent;
        private static Texture2D panelTex, rowTex;

        internal static void Ensure()
        {
            if (Panel != null && panelTex != null) return;
            panelTex = Tex(new Color(0.06f, 0.06f, 0.075f, 0.96f));
            rowTex = Tex(new Color(1f, 1f, 1f, 0.035f));
            Accent = Tex(new Color(0.91f, 0f, 0.11f, 1f));

            Panel = new GUIStyle(GUI.skin.box) { padding = new RectOffset(14, 14, 12, 12), normal = { background = panelTex } };
            Text = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, wordWrap = false, normal = { textColor = new Color(0.93f, 0.93f, 0.94f) } };
            Dim = new GUIStyle(Text) { normal = { textColor = new Color(0.55f, 0.55f, 0.6f) } };
            Good = new GUIStyle(Text) { normal = { textColor = new Color(0.35f, 0.85f, 0.5f) } };
            Bad = new GUIStyle(Text) { wordWrap = true, normal = { textColor = new Color(1f, 0.45f, 0.5f) } };
            Brand = new GUIStyle(Text) { fontStyle = FontStyle.Bold, fontSize = 14 };
            Section = new GUIStyle(Dim) { fontStyle = FontStyle.Bold, fontSize = 10 };
            Mono = new GUIStyle(Dim) { fontSize = 11 };
            Button = new GUIStyle(GUI.skin.button) { fontSize = 12, fixedHeight = 24 };
            Small = new GUIStyle(GUI.skin.button) { fontSize = 11, fixedHeight = 20 };
            Row = new GUIStyle { padding = new RectOffset(6, 6, 3, 3), normal = { background = rowTex } };
            Kicker = new GUIStyle(Text) { fontSize = 9, fontStyle = FontStyle.Bold, normal = { textColor = new Color(1f, 0.38f, 0.46f) } };
            Title = new GUIStyle(Text) { fontSize = 14, fontStyle = FontStyle.Bold };
            Gold = new GUIStyle(Text) { fontSize = 11, normal = { textColor = new Color(0.96f, 0.72f, 0.23f) } };
        }

        private static Texture2D Tex(Color c)
        {
            var t = new Texture2D(1, 1) { hideFlags = HideFlags.HideAndDontSave };
            t.SetPixel(0, 0, c);
            t.Apply();
            return t;
        }
    }
}
