using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Tudada;
using System.Security.Cryptography;

public class GameManager : MonoSingleton<GameManager>
{
    protected MonoBehaviour callbackMono;

    protected override void OnInitialized()
    {
        base.OnInitialized();




        Cursor.lockState = CursorLockMode.Confined;
        Cursor.visible = true;

        Debug.LogWarning("OnInitialized Start!!!");

        // [TudadaSDK 미지원] ReportGameStart는 WeChat 전용 API입니다.
        // TudadaSDK에서는 게임 시작 리포트 기능을 별도로 제공하지 않습니다.
        // WX.ReportGameStart();

        TudadaSDK.Instance.GetSystemInfo();

        TudadaSDK.OnShow += (res) =>
        {
            DebugConsole.Log("[Lifecycle] OnShow - App became visible");
            DebugConsole.Log($"[Lifecycle] OnShow scene: {res.scene}, query: {res.query}");
            AudioListener.pause = false;
        };

        TudadaSDK.OnHide += (res) =>
        {
            DebugConsole.Log("[Lifecycle] OnHide - App went to background");
            AudioListener.pause = true;
        };

        Debug.LogWarning("OnInitialized End!!!");

        StartCoroutine(RunAllApiTests());
    }

    void OnApplicationFocus(bool hasFocus)
    {
        DebugConsole.Log("[Lifecycle] OnApplicationFocus - hasFocus : " + hasFocus.ToString());
    }


    #region __TudadaSDK_Test__

    private IEnumerator RunAllApiTests()
    {
        yield return null;

        DebugConsole.Log("========================================");
        DebugConsole.Log("[API Test] Starting TudadaSDK API Tests");
        DebugConsole.Log("========================================");

        int passCount = 0;
        int failCount = 0;
        string lastError = null;

        // 1. IsAvailable
        try
        {
            bool isAvailable = TudadaSDK.Instance.IsAvailable();
            DebugConsole.Log($"[API Test] IsAvailable: {isAvailable} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"IsAvailable: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 2. GetSystemInfoSync
        try
        {
            var systemInfo = TudadaSDK.Instance.GetSystemInfoSync();
            DebugConsole.Log($"[API Test] GetSystemInfoSync: platform={systemInfo.platform} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"GetSystemInfoSync: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 3. GetWindowInfo
        try
        {
            var windowInfo = TudadaSDK.Instance.GetWindowInfo();
            DebugConsole.Log($"[API Test] GetWindowInfo: {windowInfo.windowWidth}x{windowInfo.windowHeight} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"GetWindowInfo: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 4. GetAppBaseInfo
        try
        {
            var appBaseInfo = TudadaSDK.Instance.GetAppBaseInfo();
            DebugConsole.Log($"[API Test] GetAppBaseInfo: SDKVersion={appBaseInfo.SDKVersion} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"GetAppBaseInfo: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 5. GetDeviceInfo
        try
        {
            var deviceInfo = TudadaSDK.Instance.GetDeviceInfo();
            DebugConsole.Log($"[API Test] GetDeviceInfo: brand={deviceInfo.brand}, model={deviceInfo.model} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"GetDeviceInfo: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 6. CanIUse
        

        // 7. GetMenuButtonBoundingClientRect
        try
        {
            var menuRect = TudadaSDK.Instance.GetMenuButtonBoundingClientRect();
            DebugConsole.Log($"[API Test] GetMenuButtonBoundingClientRect: {menuRect.width}x{menuRect.height} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"GetMenuButtonBoundingClientRect: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 8. GetStorageInfoSync
        try
        {
            var storageInfo = TudadaSDK.Instance.GetStorageInfoSync();
            DebugConsole.Log($"[API Test] GetStorageInfoSync: currentSize={storageInfo.currentSize}, limitSize={storageInfo.limitSize} - PASS");
            passCount++;
        }
        catch (Exception e)
        {
            lastError = $"GetStorageInfoSync: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 9. SetStorageSync / GetStorageSync
        try
        {
            string testKey = "_tudada_test_key_";
            string testValue = "test_value_" + DateTime.Now.Ticks;
            TudadaSDK.Instance.SetStorageSync(testKey, testValue);
            string retrieved = TudadaSDK.Instance.GetStorageSync(testKey);
            if (retrieved == testValue)
            {
                DebugConsole.Log($"[API Test] SetStorageSync/GetStorageSync: matched - PASS");
                passCount++;
            }
            else
            {
                throw new Exception($"Value mismatch: expected={testValue}, got={retrieved}");
            }
            TudadaSDK.Instance.RemoveStorageSync(testKey);
        }
        catch (Exception e)
        {
            lastError = $"SetStorageSync/GetStorageSync: {e.Message}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }

        // 10. Login (Async)
        bool loginDone = false;
        bool loginSuccess = false;
        string loginError = null;

        TudadaSDK.Instance.Login(
            onSuccess: res =>
            {
                DebugConsole.Log($"[API Test] Login: code={res.code} - PASS");
                loginSuccess = true;
                loginDone = true;
            },
            onFail: err =>
            {
                loginError = err;
                loginDone = true;
            }
        );

        float loginTimeout = 10f;
        float loginElapsed = 0f;
        while (!loginDone && loginElapsed < loginTimeout)
        {
            loginElapsed += Time.deltaTime;
            yield return null;
        }

        if (!loginDone)
        {
            lastError = "Login: Timeout";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        else if (!loginSuccess)
        {
            lastError = $"Login: {loginError}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        passCount++;

        // 11. CheckSession (Async)
        bool checkSessionDone = false;
        bool checkSessionSuccess = false;
        string checkSessionError = null;

        TudadaSDK.Instance.CheckSession(
            onSuccess: res =>
            {
                DebugConsole.Log($"[API Test] CheckSession: {res.errMsg} - PASS");
                checkSessionSuccess = true;
                checkSessionDone = true;
            },
            onFail: err =>
            {
                checkSessionError = err;
                checkSessionDone = true;
            }
        );

        float checkSessionTimeout = 10f;
        float checkSessionElapsed = 0f;
        while (!checkSessionDone && checkSessionElapsed < checkSessionTimeout)
        {
            checkSessionElapsed += Time.deltaTime;
            yield return null;
        }

        if (!checkSessionDone)
        {
            lastError = "CheckSession: Timeout";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        else if (!checkSessionSuccess)
        {
            lastError = $"CheckSession: {checkSessionError}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        passCount++;

        // 12. GetUserInfo (Async)
        bool getUserInfoDone = false;
        bool getUserInfoSuccess = false;
        string getUserInfoError = null;

        TudadaSDK.Instance.GetUserInfo(
            onSuccess: res =>
            {
                DebugConsole.Log($"[API Test] GetUserInfo: nickName={res.userInfo.nickName} - PASS");
                getUserInfoSuccess = true;
                getUserInfoDone = true;
            },
            onFail: err =>
            {
                getUserInfoError = err;
                getUserInfoDone = true;
            }
        );

        float getUserInfoTimeout = 10f;
        float getUserInfoElapsed = 0f;
        while (!getUserInfoDone && getUserInfoElapsed < getUserInfoTimeout)
        {
            getUserInfoElapsed += Time.deltaTime;
            yield return null;
        }

        if (!getUserInfoDone)
        {
            lastError = "GetUserInfo: Timeout";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        else if (!getUserInfoSuccess)
        {
            lastError = $"GetUserInfo: {getUserInfoError}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        passCount++;

        // 13. VibrateShort (Async)
        bool vibrateShortDone = false;
        bool vibrateShortSuccess = false;
        string vibrateShortError = null;

        TudadaSDK.Instance.VibrateShort(
            type: VibrateType.light,
            onSuccess: res =>
            {
                DebugConsole.Log($"[API Test] VibrateShort: {res.errMsg} - PASS");
                vibrateShortSuccess = true;
                vibrateShortDone = true;
            },
            onFail: err =>
            {
                vibrateShortError = err;
                vibrateShortDone = true;
            }
        );

        float vibrateShortTimeout = 5f;
        float vibrateShortElapsed = 0f;
        while (!vibrateShortDone && vibrateShortElapsed < vibrateShortTimeout)
        {
            vibrateShortElapsed += Time.deltaTime;
            yield return null;
        }

        if (!vibrateShortDone)
        {
            lastError = "VibrateShort: Timeout";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        else if (!vibrateShortSuccess)
        {
            lastError = $"VibrateShort: {vibrateShortError}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        passCount++;

        // 14. SetClipboardData / GetClipboardData (Async)
        bool clipboardDone = false;
        bool clipboardSuccess = false;
        string clipboardError = null;
        string clipboardTestValue = "TudadaSDK_Test_" + DateTime.Now.Ticks;

        TudadaSDK.Instance.SetClipboardData(
            data: clipboardTestValue,
            onSuccess: setRes =>
            {
                TudadaSDK.Instance.GetClipboardData(
                    onSuccess: getRes =>
                    {
                        if (getRes.data == clipboardTestValue)
                        {
                            DebugConsole.Log($"[API Test] SetClipboardData/GetClipboardData: matched - PASS");
                            clipboardSuccess = true;
                        }
                        else
                        {
                            clipboardError = $"Value mismatch: expected={clipboardTestValue}, got={getRes.data}";
                        }
                        clipboardDone = true;
                    },
                    onFail: err =>
                    {
                        clipboardError = $"GetClipboardData: {err}";
                        clipboardDone = true;
                    }
                );
            },
            onFail: err =>
            {
                clipboardError = $"SetClipboardData: {err}";
                clipboardDone = true;
            }
        );

        float clipboardTimeout = 10f;
        float clipboardElapsed = 0f;
        while (!clipboardDone && clipboardElapsed < clipboardTimeout)
        {
            clipboardElapsed += Time.deltaTime;
            yield return null;
        }

        if (!clipboardDone)
        {
            lastError = "Clipboard: Timeout";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        else if (!clipboardSuccess)
        {
            lastError = $"Clipboard: {clipboardError}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        passCount++;

        // 15. TudadaStoreSave / TudadaStoreGet (Async - Cloud Storage)
        bool tudadaStoreDone = false;
        bool tudadaStoreSuccess = false;
        string tudadaStoreError = null;
        string tudadaStoreTestKey = "_test_cloud_key_";
        string tudadaStoreTestValue = "cloud_value_" + DateTime.Now.Ticks;

        TudadaSDK.Instance.TudadaStoreSave(
            key: tudadaStoreTestKey,
            value: tudadaStoreTestValue,
            onSuccess: saveRes =>
            {
                TudadaSDK.Instance.TudadaStoreGet(
                    key: tudadaStoreTestKey,
                    onSuccess: getRes =>
                    {
                        if (getRes.value == tudadaStoreTestValue)
                        {
                            DebugConsole.Log($"[API Test] TudadaStoreSave/TudadaStoreGet: matched - PASS");
                            tudadaStoreSuccess = true;
                        }
                        else
                        {
                            tudadaStoreError = $"Value mismatch: expected={tudadaStoreTestValue}, got={getRes.value}";
                        }
                        tudadaStoreDone = true;
                    },
                    onFail: err =>
                    {
                        tudadaStoreError = $"TudadaStoreGet: {err}";
                        tudadaStoreDone = true;
                    }
                );
            },
            onFail: err =>
            {
                tudadaStoreError = $"TudadaStoreSave: {err}";
                tudadaStoreDone = true;
            }
        );

        float tudadaStoreTimeout = 15f;
        float tudadaStoreElapsed = 0f;
        while (!tudadaStoreDone && tudadaStoreElapsed < tudadaStoreTimeout)
        {
            tudadaStoreElapsed += Time.deltaTime;
            yield return null;
        }

        if (!tudadaStoreDone)
        {
            lastError = "TudadaStore: Timeout";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        else if (!tudadaStoreSuccess)
        {
            lastError = $"TudadaStore: {tudadaStoreError}";
            DebugConsole.LogError($"[API Test] {lastError} - FAIL");
            failCount++;
            yield break;
        }
        passCount++;

        // Test Complete
        DebugConsole.Log("========================================");
        DebugConsole.Log($"[API Test] COMPLETED - Pass: {passCount}, Fail: {failCount}");
        DebugConsole.Log("========================================");
    }

    public void TestLogin()
    {
        DebugConsole.Log("[TestLogin] Attempting login...");

        TudadaSDK.Instance.Login(
            onSuccess: res =>
            {
                DebugConsole.Log("[TestLogin] SUCCESS - Login completed!");
                DebugConsole.Log($"[TestLogin] code: {res.code}");
            },
            onFail: err =>
            {
                DebugConsole.LogError($"[TestLogin] FAILED: {err}");
            }
        );
    }

    public void TestGetUserInfo()
    {
        DebugConsole.Log("[TestUserInfo] Requesting user info...");

        TudadaSDK.Instance.GetUserInfo(
            onSuccess: res =>
            {
                DebugConsole.Log("[TestUserInfo] SUCCESS - Got user info!");
                DebugConsole.Log($"[TestUserInfo] nickname: {res.userInfo.nickName}");
                DebugConsole.Log($"[TestUserInfo] avatarUrl: {res.userInfo.avatarUrl}");
            },
            onFail: err =>
            {
                DebugConsole.LogError($"[TestUserInfo] FAILED: {err}");
            }
        );

    }


    private TudadaRewardedVideoAd rewardedVideoAd;
    private bool isAdLoading = false;

    public void TestRewardedVideoAd()
    {
        if (isAdLoading)
        {
            DebugConsole.LogWarning("[TestAd] Ad is already loading, please wait...");
            return;
        }

        if (rewardedVideoAd != null)
        {
            rewardedVideoAd.Destroy();
            rewardedVideoAd = null;
        }

        isAdLoading = true;
        DebugConsole.Log("[TestAd] Loading rewarded video ad...");

        DebugConsole.Log("[TestAd] Creating ad instance...");
        rewardedVideoAd = TudadaSDK.Instance.CreateRewardedVideoAd("testAd");
        DebugConsole.Log($"[TestAd] Ad instance created: {rewardedVideoAd != null}");

        DebugConsole.Log("[TestAd] Registering OnLoad callback...");
        rewardedVideoAd.OnLoad += () =>
        {
            DebugConsole.Log("[TestAd] SUCCESS - Ad loaded! Showing ad...");
            rewardedVideoAd.Show(
                onSuccess: (success) =>
                {
                    DebugConsole.Log("[TestAd] SUCCESS - Ad shown");
                },
                onFail: (failed) =>
                {
                    DebugConsole.LogError($"[TestAd] FAILED to show: {failed}");
                    isAdLoading = false;
                }
            );
        };

        DebugConsole.Log("[TestAd] Registering OnError callback...");
        rewardedVideoAd.OnError += (err) =>
        {
            DebugConsole.LogError($"[TestAd] FAILED to load: {err.errMsg}");
            isAdLoading = false;
        };

        DebugConsole.Log("[TestAd] Registering OnClose callback...");
        rewardedVideoAd.OnClose += (res) =>
        {
            DebugConsole.Log($"[TestAd] Ad closed - Rewarded: {res.isEnded}");
            rewardedVideoAd.Destroy();
            rewardedVideoAd = null;
            isAdLoading = false;
        };

        DebugConsole.Log("[TestAd] Calling Load()...");
        rewardedVideoAd.Load();
        DebugConsole.Log("[TestAd] Load() called, waiting for callback...");
    }

    public void TestKeyboardAndClipboard()
    {
        DebugConsole.Log("[TestClipboard] Showing keyboard...");

        TudadaSDK.OnKeyboardConfirm += (res) =>
        {
            DebugConsole.Log($"[TestClipboard] Keyboard confirm - input: {res.value}");

            TudadaSDK.Instance.SetClipboardData(
                data: res.value,
                onSuccess: (setRes) =>
                {
                    DebugConsole.Log($"[TestClipboard] SUCCESS - Saved to clipboard: {res.value}");
                },
                onFail: (err) =>
                {
                    DebugConsole.LogError($"[TestClipboard] FAILED to save: {err}");
                }
            );
        };

        TudadaSDK.Instance.ShowKeyboard(
            defaultValue: "",
            maxLength: 100,
            confirmType: KeyboardConfirmType.done,
            onSuccess: (res) =>
            {
                DebugConsole.Log("[TestClipboard] SUCCESS - Keyboard shown");
            },
            onFail: (err) =>
            {
                DebugConsole.LogError($"[TestClipboard] FAILED to show keyboard: {err}");
            }
        );
    }

    public void TestGetClipboardData()
    {
        DebugConsole.Log("[TestClipboard] Getting clipboard data...");

        TudadaSDK.Instance.GetClipboardData(
            onSuccess: (res) =>
            {
                DebugConsole.Log("[TestClipboard] SUCCESS - Got clipboard data!");
                DebugConsole.Log($"[TestClipboard] data: {res.data}");
            },
            onFail: (err) =>
            {
                DebugConsole.LogError($"[TestClipboard] FAILED: {err}");
            }
        );
    }

    public void TestVibrateShort()
    {
        DebugConsole.Log("[TestVibrate] Calling short vibration...");

        TudadaSDK.Instance.VibrateShort(
            type: VibrateType.medium,
            onSuccess: (res) =>
            {
                DebugConsole.Log("[TestVibrate] SUCCESS - Short vibration!");
            },
            onFail: (err) =>
            {
                DebugConsole.LogError($"[TestVibrate] FAILED: {err}");
            }
        );
    }

    public void TestVibrateLong()
    {
        DebugConsole.Log("[TestVibrate] Calling long vibration...");

        TudadaSDK.Instance.VibrateLong(
            onSuccess: (res) =>
            {
                DebugConsole.Log("[TestVibrate] SUCCESS - Long vibration!");
            },
            onFail: (err) =>
            {
                DebugConsole.LogError($"[TestVibrate] FAILED: {err}");
            }
        );
    }

    public void TestExitMiniProgram()
    {
        DebugConsole.Log("[TestExit] Exiting mini program...");

        TudadaSDK.Instance.ExitMiniProgram(
            onSuccess: (res) =>
            {
                DebugConsole.Log("[TestExit] SUCCESS - Exit completed!");
            },
            onFail: (err) =>
            {
                DebugConsole.LogError($"[TestExit] FAILED: {err}");
            }
        );
    }

    #endregion



}



public class DebugConsole
{

    public static void Log(string aLog)
    {
        Debug.Log(aLog);
    }

    public static void LogWarning(string aLog)
    {
        Debug.LogWarning(aLog);
    }
    public static void LogError(string aLog)
    {
        Debug.LogError(aLog);
    }

}

