using System;
using TMPro;
using UnityEngine;
using Arkadium;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine.UI;
#if UNITY_WEBGL && !UNITY_EDITOR
using System.Runtime.InteropServices;
#endif
using AOT;

public class ArkadiumSDKClientExample : MonoBehaviour
{
	[SerializeField] private TMP_Text versionLabel;

	private ArkadiumSDK _sdk;

#if UNITY_WEBGL && !UNITY_EDITOR
		[DllImport("__Internal")]
		public static extern void _QA(string json);
#else
	public static void _QA(string json) { }
#endif

	[System.Serializable]
	public class UIElementData
	{
		public string ID;
		public string Text;
		public Rect BoundingBox;
	}

	[System.Serializable]
	public class UIElementDataList
	{
		public List<UIElementData> Elements = new List<UIElementData>();
	}

	Rect GetScreenRect(RectTransform rectTransform)
	{
		Vector3[] corners3d = new Vector3[4];
		rectTransform.GetWorldCorners(corners3d);

		Vector2[] corners2d = new Vector2[4];
		for (int i = 0; i < 4; i++)
		{
			corners2d[i] = RectTransformUtility.WorldToScreenPoint(Camera.main, corners3d[i]);
		}

		var x0 = corners2d[0].x;
		var y1 = corners2d[2].y;
		var w = corners2d[2].x - corners2d[0].x;
		var h = corners2d[1].y - corners2d[3].y;

		return new Rect(x0, y1, w, h);
	}

	private void ExposeUiToQA()
	{
		var list = new UIElementDataList();
		foreach (var uiElement in FindObjectsOfType<Button>())
		{
			if (uiElement.gameObject.activeInHierarchy && uiElement.TryGetComponent<Graphic>(out var graphic))
			{
				if (graphic.TryGetComponent<RectTransform>(out RectTransform rt))
				{
					var rect = GetScreenRect(rt);
					list.Elements.Add(new UIElementData
					{
						ID = uiElement.name,
						Text = uiElement.TryGetComponent<TMP_Text>(out var text) ? text.text : "",
						BoundingBox = rect,
					});
				}
			}
		}
		string json = JsonUtility.ToJson(list, true);
		_QA(json);
	}

	void Start()
	{
		_sdk = ArkadiumSDK.Instance;

		//_sdk.SetLogLevel(LogLevel.NONE);
		//_sdk.SetLogLevel(LogLevel.UNITY_LOGS);
		//_sdk.SetLogLevel(LogLevel.JSLIB_LOGS);
		_sdk.SetLogLevel(LogLevel.ALL_LOGS);

		versionLabel.text += Application.version;

		Debug.Log("Initializing SDK...");
		// _sdk.InitializeDev("arkadium-sdk-for-unity", OnInitializeCb); // to use DEV env
		//_sdk.Initialize("arkadium-sdk-for-unity", OnInitializeCb); // to use PROD env

		_sdk.InitializeWithUrlParam("arkadium-sdk-for-unity", OnInitializeCb); // to use DEV env

		ExposeUiToQA();
	}

	private void OnInitializeCb(bool success)
	{
		Debug.Log($"Initialization of SDK success -> {success}");
		if (success)
		{
			_sdk.Lifecycle.OnTestReady();
			_sdk.Lifecycle.OnGameStart();
			_sdk.Lifecycle.RegisterEventCallback(ArkadiumLifecycleEvent.PauseGame, () =>
			{
				Debug.Log("[Lifecycle] pause game");
			});
			_sdk.Lifecycle.RegisterEventCallback(ArkadiumLifecycleEvent.ResumeGame, () =>
			{
				Debug.Log("[Lifecycle] resume game");
			});
		}
	}

	#region UI Cbs

	// ADS
	public void ShowInterstitialAdClicked()
	{
		_sdk.Ads.ShowInterstitialAd(30, ShowInterstitialAdCb);
	}

	public void ShowRewardAdClicked()
	{
		_sdk.Ads.ShowRewardAd(30, ShowRewardAdCb);
	}

	public void ShowBannerAd1Clicked()
	{
		_sdk.Ads.ShowBannerAd("banner_test1", ArkadiumAds.AD_320x50);
	}

	public void ShowBannerAd2Clicked()
	{
		_sdk.Ads.ShowBannerAd("banner_test2", ArkadiumAds.AD_468x60);
	}

	// ANALYTICS
	public void ConfigureProviderClicked()
	{
		_sdk.Analytics.ConfigureProvider(AnalyticsProvider.CONSOLE, "ANYTHING-GOES-IN-THIS-ONE");
		_sdk.Analytics.ConfigureProvider(AnalyticsProvider.APP_INSIGHTS, "08a82ae3-afc0-4532-b61e-c76be7277faa");
	}

	public void SendEventClicked()
	{
		var dims = new Dictionary<string, string> { { "dim1", "set-by-event" } };
		_sdk.Analytics.SendEvent("category", "action", dims);
	}

	public void SendPageViewClicked()
	{
		var dims = new Dictionary<string, string> { { "dim2", "set-by-page-view" } };
		_sdk.Analytics.SendPageView("pageName", dims);
	}

	public void SetDimensionsClicked()
	{
		var dims = new Dictionary<string, string> {
			{"dim1", "set-by-dims"},
			{"dim2", "set-by-dims"},
			{"other-one", "42" },
		};
		_sdk.Analytics.SetDimensions(dims);
	}

	// AUTH
	public void SubscribeToAuthStatusClicked()
	{
		_sdk.Auth.SubscribeToAuthStatus(SubscribeToAuthStatusCb);
	}

	public void OpenAuthFormClicked()
	{
		_sdk.Auth.OpenAuthForm(OpenAuthFormCb);
	}

	public void GetUserProfileClicked()
	{
		_sdk.Auth.GetUserProfile(GetUserProfileCb);
	}

	public void IsUserAuthorizedClicked()
	{
		_sdk.Auth.IsUserAuthorized(IsUserAuthorizedCb);
	}

	// LIFECYCLE

	public void OnTestReadyClicked()
	{
		_sdk.Lifecycle.OnTestReady();
	}

	public void OnGameStartClicked()
	{
		_sdk.Lifecycle.OnGameStart();
	}

	public void OnGameEndClicked()
	{
		_sdk.Lifecycle.OnGameEnd();
	}

	public void OnInteractClicked()
	{
		_sdk.Lifecycle.OnInteract();
	}

	public void OnGameResumeClicked()
	{
		_sdk.Lifecycle.OnGameResume();
	}

	public void OnPauseReadyClicked()
	{
		_sdk.Lifecycle.OnPauseReady();
	}

	public void OnGamePauseClicked()
	{
		_sdk.Lifecycle.OnGamePause();
	}

	public void OnChangeScoreClicked()
	{
		_sdk.Lifecycle.OnChangeScore(1447);
	}

	public void OnGemsUpdateClicked()
	{
		_sdk.Lifecycle.OnGemsUpdate();
	}

	public void OnLevelStartClicked()
	{
		_sdk.Lifecycle.OnLevelStart(1);
	}

	public void OnLevelEndClicked()
	{
		_sdk.Lifecycle.OnLevelEnd(1);
	}

	// HOST
	public void GetQueryParameterClicked()
	{
		_sdk.Host.GetQueryParameter("param", GetQueryParameterCb);
	}
	public void GetDetailsClicked()
	{
		_sdk.Host.GetDetails(GetDetailsCb);
	}
	public void OpenPurchaseFormClicked()
	{
		_sdk.Host.OpenPurchaseForm(OpenPurchaseFormCb);
	}

	// PERSISTENCE

	public void GetLocalStorageItemClicked()
	{
		_sdk.Persistence.GetLocalStorageItem("test_key", GetLocalStorageItemCb);
	}
	public void SetLocalStorageItemClicked()
	{
		var value = "{ \"universe\": 42 }";
		_sdk.Persistence.SetLocalStorageItem("test_key", value, SetLocalStorageItemCb);
	}
	public void RemoveLocalStorageItemClicked()
	{
		_sdk.Persistence.RemoveLocalStorageItem("test_key", RemoveLocalStorageItemCb);
	}
	public void GetCookieClicked()
	{
		_sdk.Persistence.GetCookie("_ga", GetCookieCb);
	}
	public void GetRemoteStorageItemClicked()
	{
		_sdk.Persistence.GetRemoteStorageItem("test_key", GetRemoteStorageItemCb);
	}
	public void SetRemoteStorageItemClicked()
	{
		var value = "{ \"universe\": 42 }";
		_sdk.Persistence.SetRemoteStorageItem("test_key", value, SetRemoteStorageItemCb);
	}
	public void RemoveRemoteStorageItemClicked()
	{
		_sdk.Persistence.RemoveRemoteStorageItem("test_key", RemoveRemoteStorageItemCb);
	}

	// WALLET
	public async void IsGemsSupported()
	{
		var isSupported = await _sdk.Wallet.IsGemsSupportedAsync();
		Debug.Log($"Gems supported: {isSupported}");
	}
	public void GetGems()
	{
		_sdk.Wallet.GetGems((int gems) =>
		{
			if (gems >= 0)
			{
				Debug.Log($"GET WALLET GEMS -> {gems}");
			}
			else
			{
				Debug.Log($"GET WALLET GEMS FAILED");
			}
		});
	}
	public void ConsumeGems()
	{
		_sdk.Wallet.ConsumeGems(1, (bool success) =>
		{
			Debug.Log($"CONSUME WALLET GEMS -> {success}");
		});
	}

	// LEADERBOARD

	public void LeaderboardIsSupported()
	{
		_sdk.Leaderboard.IsSupported((bool success) =>
		{
			Debug.Log($"LEADERBOARD IS SUPPORTED -> {success}");
		});
	}

	public void LeaderboardPostScore()
	{
		_sdk.Leaderboard.PostScore(10, (bool success) =>
		{
			Debug.Log($"LEADERBOARD POST SCORE -> {success}");
		});
	}

	public void LeaderboardGetUserScore()
	{
		_sdk.Leaderboard.GetUserScore((int score) =>
		{
			Debug.Log($"LEADERBOARD GET USER SCORE -> {score}");
		});
	}

	public void LeaderboardGetTopScores()
	{
		_sdk.Leaderboard.GetTopScores((LeaderboardEntry[] entries) =>
		{
			Debug.Log($"LEADERBOARD GET TOP SCORES:");
			foreach (var item in entries)
			{
				Debug.Log($"{item.ToString()}");
			}
		});
	}

	// TOURNAMENTS
	public async void GetTournamentsClicked()
	{
		try
		{
			var tournaments = await _sdk.Tournaments.GetTournamentsAsync();
			Debug.Log($"TOURNAMENTS FOUND: {tournaments.Length}");
			foreach (var tournament in tournaments)
			{
				Debug.Log($"Tournament: {tournament.title} (ID: {tournament.id})");
			}
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error getting tournaments: {ex.Message}");
		}
	}

	public async void HasJoinedTournamentClicked()
	{
		try
		{
			var hasJoined = await _sdk.Tournaments.HasJoinedTournamentAsync("tournament_1");
			Debug.Log($"HAS JOINED TOURNAMENT: {hasJoined}");
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error checking if joined tournament: {ex.Message}");
		}
	}

	public async void JoinTournamentClicked()
	{
		try
		{
			var success = await _sdk.Tournaments.JoinTournamentAsync("tournament_1");
			Debug.Log($"JOIN TOURNAMENT: {success}");
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error joining tournament: {ex.Message}");
		}
	}

	public async void CanSubmitScoreToTournamentClicked()
	{
		try
		{
			var canSubmit = await _sdk.Tournaments.CanSubmitScoreToTournamentAsync("tournament_1");
			Debug.Log($"CAN SUBMIT SCORE TO TOURNAMENT: {canSubmit}");
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error checking if can submit score: {ex.Message}");
		}
	}

	public async void SubmitTournamentScoreClicked()
	{
		try
		{
			var parameters = new SubmitTournamentScoreParams
			{
				tournamentId = "tournament_1",
				score = 1000,
				subscore = 500,
				metadata = new { level = 5, time = 120 }
			};

			var success = await _sdk.Tournaments.SubmitTournamentScoreAsync(parameters);
			Debug.Log($"SUBMIT TOURNAMENT SCORE: {success}");
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error submitting tournament score: {ex.Message}");
		}
	}

	public async void GetTopTournamentEntriesClicked()
	{
		try
		{
			var entries = await _sdk.Tournaments.GetTopTournamentEntriesAsync("tournament_1", 10);
			Debug.Log($"TOP TOURNAMENT ENTRIES: {entries.Length}");
			foreach (var entry in entries)
			{
				Debug.Log($"Entry: {entry.username} - Score: {entry.score} - Rank: {entry.rank}");
			}
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error getting top tournament entries: {ex.Message}");
		}
	}

	public async void GetTournamentUserEntryClicked()
	{
		try
		{
			var entry = await _sdk.Tournaments.GetTournamentUserEntryAsync("tournament_1");
			if (entry != null)
			{
				Debug.Log($"USER TOURNAMENT ENTRY: {entry.username} - Score: {entry.score} - Rank: {entry.rank}");
			}
			else
			{
				Debug.Log("USER TOURNAMENT ENTRY: No entry found");
			}
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error getting tournament user entry: {ex.Message}");
		}
	}

	public async void GetTournamentUsersEntriesClicked()
	{
		try
		{
			var userIds = new string[] { "user1", "user2", "user3" };
			var entries = await _sdk.Tournaments.GetTournamentUsersEntriesAsync("tournament_1", userIds);
			Debug.Log($"TOURNAMENT USERS ENTRIES: {entries.Length}");
			foreach (var entry in entries)
			{
				Debug.Log($"Entry: {entry.username} - Score: {entry.score} - Rank: {entry.rank}");
			}
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error getting tournament users entries: {ex.Message}");
		}
	}

	public async void GetTournamentEntriesAroundUserClicked()
	{
		try
		{
			var entries = await _sdk.Tournaments.GetTournamentEntriesAroundUserAsync("tournament_1", 5);
			Debug.Log($"TOURNAMENT ENTRIES AROUND USER: {entries.Length}");
			foreach (var entry in entries)
			{
				Debug.Log($"Entry: {entry.username} - Score: {entry.score} - Rank: {entry.rank}");
			}
		}
		catch (System.Exception ex)
		{
			Debug.LogError($"Error getting tournament entries around user: {ex.Message}");
		}
	}

	#endregion

	///////////////////////////////////////////////////

	#region SDK Cbs

	// ADS
	private void ShowInterstitialAdCb(bool success)
	{
		Debug.Log($"WE GOT AN INTERSTITIAL AD? {success}");
	}

	private void ShowRewardAdCb(int result)
	{
		Debug.Log($"WE GOT REWARDED AD? {result}");
	}

	// ANALYTICS

	// AUTH

	private void OpenAuthFormCb()
	{
		Debug.Log($"AUTH FORM WAS OPENED");
	}

	private void SubscribeToAuthStatusCb(bool isAuthenticated)
	{
		Debug.Log($"AUTH STATUS CHANGED:{isAuthenticated}");
	}

	private void GetUserProfileCb(UserProfile userProfileData)
	{
		Debug.Log($"USER PROFILE DATA: {userProfileData}");
	}

	private void IsUserAuthorizedCb(bool authorized)
	{
		Debug.Log($"IS USER AUTHORIZED: {authorized}");
	}

	// HOST

	private void GetQueryParameterCb(string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			Debug.Log($"QUERY PARAMETER FAILED");
		}
		else
		{
			Debug.Log($"QUERY PARAMETER -> {data}");
		}
	}

	private void GetDetailsCb(Details details)
	{
		if (details == null)
		{
			Debug.Log($"GET DETAILS FAILED");
		}
		else
		{
			Debug.Log($"GET DETAILS -> {details}");
		}
	}

	private void OpenPurchaseFormCb(bool result)
	{
		Debug.Log($"PURCHASE REQUEST: {result}");
	}

	// PERSISTENCE
	private void GetLocalStorageItemCb(string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			Debug.Log($"GET LOCAL STORAGE FAILED");
		}
		else
		{
			Debug.Log($"GET LOCAL STORAGE -> {data}");
		}
	}

	private void SetLocalStorageItemCb(bool success)
	{
		Debug.Log($"SET LOCAL STORAGE -> {success}");
	}

	private void RemoveLocalStorageItemCb(bool success)
	{
		Debug.Log($"REMOVE LOCAL STORAGE -> {success}");
	}

	private void GetCookieCb(string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			Debug.Log($"GET COOKIE FAILED");
		}
		else
		{
			Debug.Log($"GET COOKIE -> {data}");
		}
	}

	private void GetRemoteStorageItemCb(string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			Debug.Log($"GET REMOTE STORAGE FAILED");
		}
		else
		{
			Debug.Log($"GET REMOTE STORAGE -> {data}");
		}
	}

	private void SetRemoteStorageItemCb(bool success)
	{
		Debug.Log($"SET REMOTE STORAGE -> {success}");
	}

	private void RemoveRemoteStorageItemCb(bool success)
	{
		Debug.Log($"REMOVE REMOTE STORAGE -> {success}");
	}

	#endregion
}
