using System;
using System.Linq;
using System.Threading;
using AIImages.Helpers;
using AIImages.Models;
using AIImages.Services;
using RimWorld;
using UnityEngine;
using Verse;

#pragma warning disable IDE1006 // Naming Styles

namespace AIImages
{
    /// <summary>
    /// Окно для просмотра персонажа и генерации AI изображений
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Style",
        "IDE1006:Naming Styles",
        Justification = "RimWorld Window naming convention"
    )]
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Minor Code Smell",
        "S101:Types should be named in PascalCase",
        Justification = "RimWorld Window naming convention"
    )]
    public class Window_AIImage : Window
    {
        private Pawn pawn;
        private PawnAppearanceData appearanceData;
        private StableDiffusionSettings generationSettings;

        private Texture2D generatedImage;
        private bool isGenerating = false;
        private string generationStatus = "";
        private CancellationTokenSource cancellationTokenSource;

        // Сервисы (получаем через DI)
        private readonly IPawnDescriptionService pawnDescriptionService;
        private readonly IPromptGeneratorService promptGeneratorService;
        private readonly IStableDiffusionApiService apiService;

        public Window_AIImage(Pawn pawn)
        {
            this.pawn = pawn;
            this.doCloseX = true;
            this.doCloseButton = true;
            this.forcePause = false;
            this.absorbInputAroundWindow = false;
            this.draggable = true;
            this.preventCameraMotion = false;

            // Получаем сервисы через DI контейнер
            var services = AIImagesMod.Services;
            pawnDescriptionService = services.PawnDescriptionService;
            promptGeneratorService = services.PromptGeneratorService;
            apiService = services.ApiService;

            // Извлекаем данные персонажа
            RefreshPawnData();
        }

        public override Vector2 InitialSize => new Vector2(900f, 800f);

        private Vector2 scrollPosition = Vector2.zero;
        private Vector2 promptScrollPosition = Vector2.zero;
        private float copiedMessageTime = 0f;

        /// <summary>
        /// Обновляет данные персонажа
        /// </summary>
        private void RefreshPawnData()
        {
            appearanceData = pawnDescriptionService.ExtractAppearanceData(pawn);
            generationSettings = AIImagesMod.Settings.ToStableDiffusionSettings();
        }

        /// <summary>
        /// Освобождает ресурсы при закрытии окна
        /// </summary>
        public override void PreClose()
        {
            base.PreClose();

            // Отменяем генерацию, если она идет
            if (isGenerating && cancellationTokenSource != null)
            {
                cancellationTokenSource.Cancel();
            }

            // Освобождаем CancellationTokenSource
            cancellationTokenSource?.Dispose();
        }

        /// <summary>
        /// Обновляет текущую пешку в окне
        /// </summary>
        public void UpdatePawn(Pawn newPawn)
        {
            this.pawn = newPawn;
            RefreshPawnData();
        }

        /// <summary>
        /// Получить текущую пешку
        /// </summary>
        public Pawn CurrentPawn => pawn;

        /// <summary>
        /// Вызывается каждый кадр для обновления окна
        /// </summary>
        public override void WindowUpdate()
        {
            base.WindowUpdate();

            // Проверяем, изменилась ли выбранная пешка
            Pawn selectedPawn = Find.Selector.SelectedPawns.FirstOrDefault(p =>
                p.IsColonist && p.Spawned && p.Faction == Faction.OfPlayer
            );

            // Если выбрана новая колонистская пешка, обновляем окно
            if (selectedPawn != null && selectedPawn != pawn)
            {
                UpdatePawn(selectedPawn);
            }

            // Уменьшаем таймер сообщения о копировании
            if (copiedMessageTime > 0f)
            {
                copiedMessageTime -= Time.deltaTime;
            }
        }

        /// <summary>
        /// Асинхронная генерация изображения с поддержкой отмены
        /// </summary>
        private async System.Threading.Tasks.Task GenerateImageAsync()
        {
            if (isGenerating)
                return;

            // Создаем новый CancellationTokenSource
            cancellationTokenSource?.Dispose();
            cancellationTokenSource = new CancellationTokenSource();

            isGenerating = true;
            generationStatus = "AIImages.Generation.InProgress".Translate();

            try
            {
                // Генерируем промпты
                string positivePrompt = promptGeneratorService.GeneratePositivePrompt(
                    appearanceData,
                    generationSettings
                );
                string negativePrompt = promptGeneratorService.GenerateNegativePrompt(
                    generationSettings
                );

                // Создаем запрос
                var request = new GenerationRequest
                {
                    Prompt = positivePrompt,
                    NegativePrompt = negativePrompt,
                    Steps = generationSettings.Steps,
                    CfgScale = generationSettings.CfgScale,
                    Width = generationSettings.Width,
                    Height = generationSettings.Height,
                    Sampler = generationSettings.Sampler,
                    Scheduler = generationSettings.Scheduler,
                    Seed = generationSettings.Seed,
                    Model = AIImagesMod.Settings.apiEndpoint,
                };

                // Генерируем изображение с поддержкой отмены
                var result = await apiService.GenerateImageAsync(
                    request,
                    cancellationTokenSource.Token
                );

                if (result.Success)
                {
                    // Загружаем текстуру
                    generatedImage = new Texture2D(2, 2);
                    generatedImage.LoadImage(result.ImageData);
                    generationStatus = "AIImages.Generation.Success".Translate();

                    Messages.Message(
                        "AIImages.Generation.SavedTo".Translate(result.SavedPath),
                        MessageTypeDefOf.PositiveEvent
                    );
                }
                else
                {
                    generationStatus =
                        $"AIImages.Generation.Failed".Translate() + ": {result.ErrorMessage}";
                    Messages.Message(generationStatus, MessageTypeDefOf.RejectInput);
                }
            }
            catch (OperationCanceledException)
            {
                generationStatus = "AIImages.Generation.Cancelled".Translate();
                Log.Message("[AI Images] Generation cancelled by user");
            }
            catch (Exception ex)
            {
                generationStatus = $"Error: {ex.Message}";
                Log.Error($"[AI Images] Generation error: {ex}");
                Messages.Message(
                    $"AIImages.Generation.Error".Translate() + ": {ex.Message}",
                    MessageTypeDefOf.RejectInput
                );
            }
            finally
            {
                isGenerating = false;
            }
        }

        /// <summary>
        /// Запускает генерацию изображения (обертка для безопасного fire-and-forget)
        /// </summary>
        private void StartGeneration()
        {
            AsyncHelper.FireAndForget(GenerateImageAsync(), "Image Generation");
        }

        /// <summary>
        /// Отменяет генерацию изображения
        /// </summary>
        private void CancelGeneration()
        {
            if (isGenerating && cancellationTokenSource != null)
            {
                cancellationTokenSource.Cancel();
                generationStatus = "AIImages.Generation.Cancelling".Translate();
            }
        }

        public override void DoWindowContents(Rect inRect)
        {
            float curY = 0f;

            // Заголовок
            Text.Font = GameFont.Medium;
            Widgets.Label(
                new Rect(0f, curY, inRect.width, 40f),
                "AIImages.Window.Title".Translate()
            );
            curY += 45f;

            // Имя пешки
            Text.Font = GameFont.Small;
            Widgets.Label(
                new Rect(0f, curY, inRect.width, 30f),
                "AIImages.Window.PawnLabel".Translate(pawn.NameShortColored.Resolve())
            );
            curY += 40f;

            // Разделитель
            Widgets.DrawLineHorizontal(0f, curY, inRect.width);
            curY += 10f;

            // Разделяем на две колонки: левая - информация, правая - изображение
            float leftColumnWidth = inRect.width * 0.55f;
            float rightColumnWidth = inRect.width * 0.42f;
            float columnGap = inRect.width * 0.03f;

            // Левая колонка - прокручиваемая информация
            Rect leftColumnRect = new Rect(0f, curY, leftColumnWidth, inRect.height - curY);
            DrawLeftColumn(leftColumnRect);

            // Правая колонка - превью и управление
            Rect rightColumnRect = new Rect(
                leftColumnWidth + columnGap,
                curY,
                rightColumnWidth,
                inRect.height - curY
            );
            DrawRightColumn(rightColumnRect);
        }

        private void DrawLeftColumn(Rect rect)
        {
            Rect scrollViewRect = new Rect(0f, 0f, rect.width - 20f, CalculateContentHeight());
            Widgets.BeginScrollView(rect, ref scrollPosition, scrollViewRect);

            float contentY = 0f;

            // Секция "Внешность"
            Text.Font = GameFont.Medium;
            Widgets.Label(
                new Rect(10f, contentY, scrollViewRect.width - 20f, 30f),
                "AIImages.Appearance.SectionTitle".Translate()
            );
            contentY += 35f;

            Text.Font = GameFont.Small;
            string appearanceText = pawnDescriptionService.GetAppearanceDescription(pawn);
            float appearanceHeight = Text.CalcHeight(appearanceText, scrollViewRect.width - 30f);
            Widgets.Label(
                new Rect(20f, contentY, scrollViewRect.width - 30f, appearanceHeight),
                appearanceText
            );
            contentY += appearanceHeight + 20f;

            // Разделитель
            Widgets.DrawLineHorizontal(10f, contentY, scrollViewRect.width - 20f);
            contentY += 15f;

            // Секция "Одежда"
            Text.Font = GameFont.Medium;
            Widgets.Label(
                new Rect(10f, contentY, scrollViewRect.width - 20f, 30f),
                "AIImages.Apparel.SectionTitle".Translate()
            );
            contentY += 35f;

            Text.Font = GameFont.Small;
            string apparelText = pawnDescriptionService.GetApparelDescription(pawn);
            float apparelHeight = Text.CalcHeight(apparelText, scrollViewRect.width - 30f);
            Widgets.Label(
                new Rect(20f, contentY, scrollViewRect.width - 30f, apparelHeight),
                apparelText
            );

            Widgets.EndScrollView();
        }

        private void DrawRightColumn(Rect rect)
        {
            float curY = 0f;

            // Превью изображения
            if (generatedImage != null)
            {
                float imageSize = Mathf.Min(rect.width, 400f);
                Rect imageRect = new Rect(
                    rect.x + (rect.width - imageSize) / 2f,
                    rect.y + curY,
                    imageSize,
                    imageSize
                );
                GUI.DrawTexture(imageRect, generatedImage);
                curY += imageSize + 10f;
            }
            else
            {
                // Placeholder для изображения
                float placeholderSize = Mathf.Min(rect.width, 300f);
                Rect placeholderRect = new Rect(
                    rect.x + (rect.width - placeholderSize) / 2f,
                    rect.y + curY,
                    placeholderSize,
                    placeholderSize
                );
                Widgets.DrawBoxSolid(placeholderRect, new Color(0.2f, 0.2f, 0.2f));
                Text.Anchor = TextAnchor.MiddleCenter;
                Widgets.Label(placeholderRect, "AIImages.Generation.NoImage".Translate());
                Text.Anchor = TextAnchor.UpperLeft;
                curY += placeholderSize + 10f;
            }

            // Статус генерации
            if (!string.IsNullOrEmpty(generationStatus))
            {
                Text.Font = GameFont.Small;
                float statusHeight = Text.CalcHeight(generationStatus, rect.width);
                Widgets.Label(
                    new Rect(rect.x, rect.y + curY, rect.width, statusHeight),
                    generationStatus
                );
                curY += statusHeight + 10f;
            }

            // Кнопка генерации/отмены
            Text.Font = GameFont.Small;
            if (isGenerating)
            {
                // Показываем кнопку отмены во время генерации
                if (
                    Widgets.ButtonText(
                        new Rect(rect.x, rect.y + curY, rect.width, 35f),
                        "AIImages.Generation.Cancel".Translate()
                    )
                )
                {
                    CancelGeneration();
                }
            }
            else
            {
                // Показываем кнопку генерации
                if (
                    Widgets.ButtonText(
                        new Rect(rect.x, rect.y + curY, rect.width, 35f),
                        "AIImages.Generation.Generate".Translate()
                    )
                )
                {
                    StartGeneration();
                }
            }
            curY += 40f;

            // Промпт секция
            Text.Font = GameFont.Medium;
            Widgets.Label(
                new Rect(rect.x, rect.y + curY, rect.width, 30f),
                "AIImages.Prompt.SectionTitle".Translate()
            );
            curY += 35f;

            // Получаем промпт
            Text.Font = GameFont.Tiny;
            string promptText = promptGeneratorService.GeneratePositivePrompt(
                appearanceData,
                generationSettings
            );

            // Фиксированная высота для области промпта
            float promptBoxHeight = 150f;
            float actualPromptHeight = Text.CalcHeight(promptText, rect.width - 20f);

            Rect promptOuterRect = new Rect(rect.x, rect.y + curY, rect.width, promptBoxHeight);
            Rect promptViewRect = new Rect(0f, 0f, rect.width - 20f, actualPromptHeight);

            // Рисуем фон
            Widgets.DrawBoxSolid(promptOuterRect, new Color(0.1f, 0.1f, 0.1f, 0.5f));

            // Рисуем промпт с прокруткой
            Widgets.BeginScrollView(
                promptOuterRect.ContractedBy(5f),
                ref promptScrollPosition,
                promptViewRect
            );
            Widgets.Label(
                new Rect(0f, 0f, promptViewRect.width, promptViewRect.height),
                promptText
            );
            Widgets.EndScrollView();

            curY += promptBoxHeight + 10f;

            // Кнопка копирования промпта
            if (
                Widgets.ButtonText(
                    new Rect(rect.x, rect.y + curY, rect.width / 2f - 5f, 30f),
                    "AIImages.Prompt.CopyButton".Translate()
                )
            )
            {
                GUIUtility.systemCopyBuffer = promptText;
                copiedMessageTime = 2f;
            }

            // Кнопка обновления данных
            if (
                Widgets.ButtonText(
                    new Rect(
                        rect.x + rect.width / 2f + 5f,
                        rect.y + curY,
                        rect.width / 2f - 5f,
                        30f
                    ),
                    "AIImages.Window.Refresh".Translate()
                )
            )
            {
                RefreshPawnData();
            }

            // Сообщение о копировании
            if (copiedMessageTime > 0f)
            {
                curY += 35f;
                GUI.color = new Color(0f, 1f, 0f, copiedMessageTime / 2f);
                Widgets.Label(
                    new Rect(rect.x, rect.y + curY, rect.width, 25f),
                    "AIImages.Prompt.Copied".Translate()
                );
                GUI.color = Color.white;
            }
        }

        private float CalculateContentHeight()
        {
            float height = 0f;

            // Заголовок "Внешность"
            height += 35f;

            // Текст внешности
            string appearanceText = pawnDescriptionService.GetAppearanceDescription(pawn);
            height += Text.CalcHeight(appearanceText, 400f) + 20f;

            // Разделитель
            height += 15f;

            // Заголовок "Одежда"
            height += 35f;

            // Текст одежды
            string apparelText = pawnDescriptionService.GetApparelDescription(pawn);
            height += Text.CalcHeight(apparelText, 400f) + 20f;

            // Дополнительный отступ
            height += 50f;

            return height;
        }
    }
}
