using System;
using System.Threading.Tasks;
using RimWorld;
using Verse;

namespace AIImages.Helpers
{
    /// <summary>
    /// Вспомогательный класс для правильной обработки асинхронных операций в RimWorld
    /// Предотвращает fire-and-forget паттерн и обеспечивает централизованную обработку ошибок
    /// </summary>
    public static class AsyncHelper
    {
        /// <summary>
        /// Выполняет асинхронную задачу с обработкой ошибок
        /// </summary>
        public static async Task RunAsync(Func<Task> taskFunc, string operationName = "Operation")
        {
            try
            {
                await taskFunc();
            }
            catch (OperationCanceledException)
            {
                Log.Message($"[AI Images] {operationName} was cancelled");
                Messages.Message($"{operationName} was cancelled", MessageTypeDefOf.RejectInput);
            }
            catch (Exception ex)
            {
                Log.Error($"[AI Images] Error in {operationName}: {ex.Message}\n{ex.StackTrace}");
                Messages.Message(
                    $"Error in {operationName}: {ex.Message}",
                    MessageTypeDefOf.RejectInput
                );
            }
        }

        /// <summary>
        /// Выполняет асинхронную задачу с обработкой ошибок и callback при успехе
        /// </summary>
        public static async Task RunAsync<T>(
            Func<Task<T>> taskFunc,
            Action<T> onSuccess,
            string operationName = "Operation"
        )
        {
            try
            {
                T result = await taskFunc();
                onSuccess?.Invoke(result);
            }
            catch (OperationCanceledException)
            {
                Log.Message($"[AI Images] {operationName} was cancelled");
                Messages.Message($"{operationName} was cancelled", MessageTypeDefOf.RejectInput);
            }
            catch (Exception ex)
            {
                Log.Error($"[AI Images] Error in {operationName}: {ex.Message}\n{ex.StackTrace}");
                Messages.Message(
                    $"Error in {operationName}: {ex.Message}",
                    MessageTypeDefOf.RejectInput
                );
            }
        }

        /// <summary>
        /// Выполняет асинхронную задачу с полным контролем: onSuccess, onError, onCancel
        /// </summary>
        public static async Task RunAsync<T>(
            Func<Task<T>> taskFunc,
            Action<T> onSuccess,
            Action<Exception> onError = null,
            Action onCancel = null,
            string operationName = "Operation"
        )
        {
            try
            {
                T result = await taskFunc();
                onSuccess?.Invoke(result);
            }
            catch (OperationCanceledException)
            {
                Log.Message($"[AI Images] {operationName} was cancelled");

                if (onCancel != null)
                {
                    onCancel();
                }
                else
                {
                    Messages.Message(
                        $"{operationName} was cancelled",
                        MessageTypeDefOf.RejectInput
                    );
                }
            }
            catch (Exception ex)
            {
                Log.Error($"[AI Images] Error in {operationName}: {ex.Message}\n{ex.StackTrace}");

                if (onError != null)
                {
                    onError(ex);
                }
                else
                {
                    Messages.Message(
                        $"Error in {operationName}: {ex.Message}",
                        MessageTypeDefOf.RejectInput
                    );
                }
            }
        }

        /// <summary>
        /// Безопасно выполняет Task без ожидания результата, с логированием ошибок
        /// Используется когда нужен fire-and-forget, но с обработкой ошибок
        /// </summary>
        public static void FireAndForget(Task task, string operationName = "Background operation")
        {
            if (task == null)
                return;

            task.ContinueWith(
                t =>
                {
                    if (t.IsFaulted && t.Exception != null)
                    {
                        var ex = t.Exception.GetBaseException();
                        Log.Error(
                            $"[AI Images] Error in {operationName}: {ex.Message}\n{ex.StackTrace}"
                        );
                    }
                    else if (t.IsCanceled)
                    {
                        Log.Message($"[AI Images] {operationName} was cancelled");
                    }
                },
                TaskScheduler.Default
            );
        }
    }
}
