

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using Newtonsoft.Json;

namespace com.al_arcade.shared
{
    public class SSApiManager : MonoBehaviour
    {
        public static SSApiManager Instance { get; private set; }

        [Header("API Configuration")]
        [SerializeField] private string baseUrl =
            "https://phpserver.caprover.al-arcade.com/ssbook/api.php";

        [SerializeField] private int timeoutSeconds = 15;


        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }


        public static SSApiManager EnsureInstance()
        {
            if (Instance != null) return Instance;
            var go = new GameObject("[SSApiManager]");
            Instance = go.AddComponent<SSApiManager>();
            DontDestroyOnLoad(go);
            return Instance;
        }


        public IEnumerator GetRequest(string action,
            Dictionary<string, string> parameters,
            Action<string> onSuccess,
            Action<string> onError)
        {
            string url = baseUrl + "?action=" + UnityWebRequest.EscapeURL(action);
            if (parameters != null)
            {
                foreach (var kv in parameters)
                {
                    url += "&" + UnityWebRequest.EscapeURL(kv.Key) +
                           "=" + UnityWebRequest.EscapeURL(kv.Value);
                }
            }

            using var req = UnityWebRequest.Get(url);
            req.timeout = timeoutSeconds;

            yield return req.SendWebRequest();

            if (req.result != UnityWebRequest.Result.Success)
            {
                string errorMsg = req.error ?? "Network error";
                Debug.LogWarning($"[SSApi] Request failed: {errorMsg}");
                onError?.Invoke(errorMsg);
                yield break;
            }

            string json = req.downloadHandler.text;
            onSuccess?.Invoke(json);
        }


        public IEnumerator Ping(Action<bool> onResult)
        {
            yield return GetRequest("ping", null,
                json => onResult?.Invoke(true),
                err => onResult?.Invoke(false));
        }


        public IEnumerator ValidateClassCode(string code,
            Action<ClassInfo> onSuccess,
            Action<string> onError)
        {
            var p = new Dictionary<string, string> { { "class_code", code } };

            yield return GetRequest("validate_class", p,
                json =>
                {
                    try
                    {
                        var resp = JsonConvert.DeserializeObject<ValidateClassResponse>(json);
                        if (resp.success && resp.classInfo != null)
                            onSuccess?.Invoke(resp.classInfo);
                        else
                            onError?.Invoke(resp.error ?? "Validation failed");
                    }
                    catch (Exception e)
                    {
                        Debug.LogError($"[SSApi] Parse error: {e.Message}");
                        onError?.Invoke("Failed to parse server response");
                    }
                },
                onError);
        }


        public IEnumerator GetGrades(Action<GradeInfo[]> onSuccess,
            Action<string> onError)
        {
            yield return GetRequest("get_grades", null,
                json =>
                {
                    try
                    {
                        var resp = JsonConvert.DeserializeObject<GradesResponse>(json);
                        if (resp.success)
                            onSuccess?.Invoke(resp.grades ?? Array.Empty<GradeInfo>());
                        else
                            onError?.Invoke(resp.error ?? "Failed to load grades");
                    }
                    catch (Exception e)
                    {
                        onError?.Invoke("Parse error: " + e.Message);
                    }
                },
                onError);
        }


        public IEnumerator FetchMcq(string buildType, string classCode,
            int count, int gradeId,
            Action<McqQuestion[]> onSuccess,
            Action<string> onError)
        {
            var p = new Dictionary<string, string>
            {
                { "build_type", buildType },
                { "count", count.ToString() }
            };
            if (gradeId > 0) p["grade_id"] = gradeId.ToString();
            if (buildType == "teacher" && !string.IsNullOrEmpty(classCode))
                p["class_code"] = classCode;

            yield return GetRequest("get_mcq", p,
                json =>
                {
                    try
                    {
                        var resp = JsonConvert.DeserializeObject<ApiResponse<McqQuestion>>(json);
                        if (resp.success && resp.questions != null)
                            onSuccess?.Invoke(resp.questions);
                        else
                            onError?.Invoke(resp.error ?? "No questions returned");
                    }
                    catch (Exception e)
                    {
                        onError?.Invoke("Parse error: " + e.Message);
                    }
                },
                onError);
        }


        public IEnumerator FetchTf(string buildType, string classCode,
            int count, int gradeId,
            Action<TfQuestion[]> onSuccess,
            Action<string> onError)
        {
            var p = new Dictionary<string, string>
            {
                { "build_type", buildType },
                { "count", count.ToString() }
            };
            if (gradeId > 0) p["grade_id"] = gradeId.ToString();
            if (buildType == "teacher" && !string.IsNullOrEmpty(classCode))
                p["class_code"] = classCode;

            yield return GetRequest("get_tf", p,
                json =>
                {
                    try
                    {
                        var resp = JsonConvert.DeserializeObject<ApiResponse<TfQuestion>>(json);
                        if (resp.success && resp.questions != null)
                            onSuccess?.Invoke(resp.questions);
                        else
                            onError?.Invoke(resp.error ?? "No questions returned");
                    }
                    catch (Exception e)
                    {
                        onError?.Invoke("Parse error: " + e.Message);
                    }
                },
                onError);
        }


        public IEnumerator FetchCs(string buildType, string classCode,
            int count, int gradeId,
            Action<CsQuestion[]> onSuccess,
            Action<string> onError)
        {
            var p = new Dictionary<string, string>
            {
                { "build_type", buildType },
                { "count", count.ToString() }
            };
            if (gradeId > 0) p["grade_id"] = gradeId.ToString();
            if (buildType == "teacher" && !string.IsNullOrEmpty(classCode))
                p["class_code"] = classCode;

            yield return GetRequest("get_cs", p,
                json =>
                {
                    try
                    {
                        var resp = JsonConvert.DeserializeObject<ApiResponse<CsQuestion>>(json);
                        if (resp.success && resp.questions != null)
                            onSuccess?.Invoke(resp.questions);
                        else
                            onError?.Invoke(resp.error ?? "No questions returned");
                    }
                    catch (Exception e)
                    {
                        onError?.Invoke("Parse error: " + e.Message);
                    }
                },
                onError);
        }
    }
}
