using System;
using System.Threading.Tasks;
using UnityEngine;
using Arkadium;

namespace Arkadium.Examples
{
    /// <summary>
    /// Example demonstrating the tournaments API using the new promise-based interop approach
    /// </summary>
    public class TournamentsExample : MonoBehaviour
    {
        private ArkadiumTournaments _tournaments;

        void Start()
        {
            _tournaments = new ArkadiumTournaments();

            // Example 1: Using async/await (recommended)
            _ = DemonstrateAsyncAwait();

            // Example 2: Using callbacks (legacy approach)
            DemonstrateCallbacks();
        }

        /// <summary>
        /// Example using the new async/await approach
        /// </summary>
        private async Task DemonstrateAsyncAwait()
        {
            Debug.Log("=== Tournaments Async/Await Example ===");

            try
            {
                // Get all available tournaments
                var tournaments = await _tournaments.GetTournamentsAsync();
                Debug.Log($"Found {tournaments.Length} tournaments");

                if (tournaments.Length > 0)
                {
                    var firstTournament = tournaments[0];
                    Debug.Log($"First tournament: {firstTournament.title} (ID: {firstTournament.id})");

                    // Check if user has joined this tournament
                    var hasJoined = await _tournaments.HasJoinedTournamentAsync(firstTournament.id);
                    Debug.Log($"Has joined tournament: {hasJoined}");

                    if (!hasJoined)
                    {
                        // Join the tournament
                        var joined = await _tournaments.JoinTournamentAsync(firstTournament.id);
                        Debug.Log($"Joined tournament: {joined}");

                        if (joined)
                        {
                            // Check if can submit score
                            var canSubmit = await _tournaments.CanSubmitScoreToTournamentAsync(firstTournament.id);
                            Debug.Log($"Can submit score: {canSubmit}");

                            if (canSubmit)
                            {
                                // Submit a score
                                var scoreParams = new SubmitTournamentScoreParams
                                {
                                    tournamentId = firstTournament.id,
                                    score = 1000,
                                    subscore = 50
                                };

                                var submitted = await _tournaments.SubmitTournamentScoreAsync(scoreParams);
                                Debug.Log($"Score submitted: {submitted}");
                            }
                        }
                    }

                    // Get top entries
                    var topEntries = await _tournaments.GetTopTournamentEntriesAsync(firstTournament.id, 10);
                    Debug.Log($"Top {topEntries.Length} entries retrieved");

                    // Get user's entry
                    var userEntry = await _tournaments.GetTournamentUserEntryAsync(firstTournament.id);
                    if (userEntry != null)
                    {
                        Debug.Log($"User rank: {userEntry.rank}, Score: {userEntry.score}");
                    }

                    // Get entries around user
                    var aroundUser = await _tournaments.GetTournamentEntriesAroundUserAsync(firstTournament.id, 5);
                    Debug.Log($"Found {aroundUser.Length} entries around user");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error in tournaments async example: {ex.Message}");
            }
        }

        /// <summary>
        /// Example using the legacy callback approach
        /// </summary>
        private void DemonstrateCallbacks()
        {
            Debug.Log("=== Tournaments Callback Example ===");

            _tournaments.GetTournaments((tournaments) =>
            {
                Debug.Log($"Found {tournaments.Length} tournaments (callback)");

                if (tournaments.Length > 0)
                {
                    var firstTournament = tournaments[0];

                    _tournaments.HasJoinedTournament(firstTournament.id, (hasJoined) =>
                    {
                        Debug.Log($"Has joined tournament: {hasJoined} (callback)");

                        if (!hasJoined)
                        {
                            _tournaments.JoinTournament(firstTournament.id, (joined) =>
                            {
                                Debug.Log($"Joined tournament: {joined} (callback)");

                                if (joined)
                                {
                                    var scoreParams = new SubmitTournamentScoreParams
                                    {
                                        tournamentId = firstTournament.id,
                                        score = 500,
                                        subscore = 25
                                    };

                                    _tournaments.SubmitTournamentScore(scoreParams, (submitted) =>
                                    {
                                        Debug.Log($"Score submitted: {submitted} (callback)");
                                    });
                                }
                            });
                        }
                    });
                }
            });
        }

        /// <summary>
        /// Example showing error handling with async/await
        /// </summary>
        private async Task DemonstrateErrorHandling()
        {
            Debug.Log("=== Tournaments Error Handling Example ===");

            try
            {
                // This might fail if the API is not available
                var tournaments = await _tournaments.GetTournamentsAsync();
                Debug.Log($"Successfully got {tournaments.Length} tournaments");
            }
            catch (Exception ex)
            {
                Debug.LogError($"Failed to get tournaments: {ex.Message}");
                // Handle the error gracefully
            }
        }

        /// <summary>
        /// Example showing parallel operations
        /// </summary>
        private async Task DemonstrateParallelOperations()
        {
            Debug.Log("=== Tournaments Parallel Operations Example ===");

            try
            {
                // Run multiple operations in parallel
                var tournamentsTask = _tournaments.GetTournamentsAsync();
                var topEntriesTask = _tournaments.GetTopTournamentEntriesAsync("tournament1", 10);

                // Wait for both to complete
                await Task.WhenAll(tournamentsTask, topEntriesTask);

                var tournaments = tournamentsTask.Result;
                var topEntries = topEntriesTask.Result;

                Debug.Log($"Parallel results - Tournaments: {tournaments.Length}, Top entries: {topEntries.Length}");
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error in parallel operations: {ex.Message}");
            }
        }

        /// <summary>
        /// Example showing tournament workflow
        /// </summary>
        private async Task DemonstrateTournamentWorkflow()
        {
            Debug.Log("=== Tournament Workflow Example ===");

            try
            {
                // 1. Get available tournaments
                var tournaments = await _tournaments.GetTournamentsAsync();
                if (tournaments.Length == 0)
                {
                    Debug.Log("No tournaments available");
                    return;
                }

                var tournament = tournaments[0];
                Debug.Log($"Selected tournament: {tournament.title}");

                // 2. Check if user has joined
                var hasJoined = await _tournaments.HasJoinedTournamentAsync(tournament.id);
                if (!hasJoined)
                {
                    Debug.Log("Joining tournament...");
                    var joined = await _tournaments.JoinTournamentAsync(tournament.id);
                    if (!joined)
                    {
                        Debug.LogError("Failed to join tournament");
                        return;
                    }
                }

                // 3. Check if can submit score
                var canSubmit = await _tournaments.CanSubmitScoreToTournamentAsync(tournament.id);
                if (!canSubmit)
                {
                    Debug.Log("Cannot submit score to tournament");
                    return;
                }

                // 4. Submit score
                var scoreParams = new SubmitTournamentScoreParams
                {
                    tournamentId = tournament.id,
                    score = UnityEngine.Random.Range(100, 1000),
                    subscore = UnityEngine.Random.Range(0, 100)
                };

                var submitted = await _tournaments.SubmitTournamentScoreAsync(scoreParams);
                Debug.Log($"Score submitted successfully: {submitted}");

                // 5. Get updated rankings
                var userEntry = await _tournaments.GetTournamentUserEntryAsync(tournament.id);
                if (userEntry != null)
                {
                    Debug.Log($"User rank: {userEntry.rank}, Score: {userEntry.score}");
                }

                var topEntries = await _tournaments.GetTopTournamentEntriesAsync(tournament.id, 5);
                Debug.Log($"Top 5 players:");
                for (int i = 0; i < topEntries.Length; i++)
                {
                    var entry = topEntries[i];
                    Debug.Log($"  {i + 1}. {entry.username}: {entry.score} points");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error in tournament workflow: {ex.Message}");
            }
        }

        // UI Button handlers for testing
        public void OnTestAsyncAwait()
        {
            _ = DemonstrateAsyncAwait();
        }

        public void OnTestCallbacks()
        {
            DemonstrateCallbacks();
        }

        public void OnTestErrorHandling()
        {
            _ = DemonstrateErrorHandling();
        }

        public void OnTestParallel()
        {
            _ = DemonstrateParallelOperations();
        }

        public void OnTestWorkflow()
        {
            _ = DemonstrateTournamentWorkflow();
        }
    }
}