using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

namespace Davanci.Nexus.Editor
{
    // Play Games Android setup for Nexus Setup (reflection — no hard GPGS dependency).
    public static class NexusGpgsSetup
    {
        const string SettingsPath = "ProjectSettings/GooglePlayGameSettings.txt";
        const string SetupDoneKey = "android.SetupDone";
        const string WebClientKey = "and.ClientId";
        const string ResourcesKey = "and.ResourceData";
        const string SetupTypeName = "GooglePlayGames.Editor.GPGSAndroidSetupUI";

        public static bool IsAvailable =>
            NexusInstaller.Sdks.Exists(s => s.Id == "gpgs" && s.IsInstalled);

        public static bool IsConfigured => ReadSetting(SetupDoneKey) == "true";

        public static void SyncFromGpgsSettings(NexusConfig config)
        {
            if (config == null) return;

            if (string.IsNullOrEmpty(config.gpgsWebClientId))
            {
                string saved = ReadSetting(WebClientKey);
                if (!string.IsNullOrEmpty(saved))
                    config.gpgsWebClientId = saved;
            }

            if (string.IsNullOrEmpty(config.gpgsResourcesXml))
            {
                string saved = ReadSetting(ResourcesKey);
                if (!string.IsNullOrEmpty(saved))
                    config.gpgsResourcesXml = saved;
            }
        }

        public static string Apply(NexusConfig config)
        {
            if (config == null)
                return "No NexusConfig found.";

            if (!IsAvailable)
                return "Google Play Games plugin is not installed. Install it in step 2 first.";

            if (string.IsNullOrWhiteSpace(config.gpgsResourcesXml))
                return "Paste the Android Resources XML from the Play Console first.";

            EditorUtility.SetDirty(config);
            AssetDatabase.SaveAssetIfDirty(config);

            var setupType = FindType(SetupTypeName);
            if (setupType == null)
                return "Play Games editor types not found. Reimport the plugin.";

            var method = setupType.GetMethod(
                "PerformSetup",
                BindingFlags.Public | BindingFlags.Static,
                null,
                new[] { typeof(string), typeof(string), typeof(string), typeof(string), typeof(string) },
                null);

            if (method == null)
                return "Play Games setup API not found.";

            try
            {
                bool ok = (bool)method.Invoke(null, new object[]
                {
                    config.gpgsWebClientId ?? "",
                    "Assets",
                    "GPGSIds",
                    config.gpgsResourcesXml,
                    null
                });

                return ok
                    ? "Play Games Android setup complete. Cloud Save can use the Saved Games slot on device."
                    : "Setup failed. Check the Android Resources XML contains a valid app_id, and that the Web Client ID matches your Play Console OAuth client (if provided).";
            }
            catch (TargetInvocationException e)
            {
                return "Setup failed: " + (e.InnerException?.Message ?? e.Message);
            }
        }

        static Type FindType(string fullName)
        {
            var type = Type.GetType(fullName);
            if (type != null) return type;

            foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = asm.GetType(fullName);
                if (type != null) return type;
            }

            return null;
        }

        static string ReadSetting(string key)
        {
            string path = Path.Combine(Directory.GetParent(Application.dataPath)?.FullName ?? "", SettingsPath);
            if (!File.Exists(path)) return "";

            foreach (string line in File.ReadAllLines(path))
            {
                if (string.IsNullOrWhiteSpace(line) || !line.Contains("=")) continue;
                int eq = line.IndexOf('=');
                if (line.Substring(0, eq).Trim() != key) continue;
                string raw = line.Substring(eq + 1).Trim();
                return string.IsNullOrEmpty(raw) ? "" : UnityWebRequest.UnEscapeURL(raw);
            }

            return "";
        }
    }
}
