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;

        // Прогресс генерации
        private double generationProgress = 0.0;
        private int currentStep = 0;
        private int totalSteps = 0;
        private double etaSeconds = 0.0;

        // Сервисы (получаем через 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 = false; // Убираем дублирующую кнопку "Закрыть"
            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 mainScrollPosition = Vector2.zero;
        private Vector2 promptScrollPosition = Vector2.zero;
        private Vector2 negativePromptScrollPosition = Vector2.zero;
        private float copiedMessageTime = 0f;

        // Состояние сворачиваемых секций промптов
        private bool showPositivePrompt = false;
        private bool showNegativePrompt = false;

        /// <summary>
        /// Обновляет данные персонажа
        /// </summary>
        private void RefreshPawnData()
        {
            DebugLogger.Log($"[AI Images] RefreshPawnData called for {pawn?.Name}");

            appearanceData = pawnDescriptionService.ExtractAppearanceData(pawn);
            generationSettings = AIImagesMod.Settings.ToStableDiffusionSettings();

            // Загружаем сохраненный портрет, если есть
            LoadSavedPortrait();

            DebugLogger.Log($"[AI Images] RefreshPawnData completed for {pawn?.Name}");
        }

        /// <summary>
        /// Загружает сохраненный портрет персонажа
        /// </summary>
        private void LoadSavedPortrait()
        {
            DebugLogger.Log($"[AI Images] LoadSavedPortrait called for {pawn?.Name}");

            if (PawnPortraitHelper.HasPortrait(pawn))
            {
                DebugLogger.Log($"[AI Images] Portrait found for {pawn?.Name}, loading...");
                generatedImage = PawnPortraitHelper.LoadPortrait(pawn);
                if (generatedImage != null)
                {
                    generationStatus = "AIImages.Generation.LoadedFromSave".Translate();
                    DebugLogger.Log($"[AI Images] Successfully loaded portrait for {pawn?.Name}");
                    DebugLogger.Log(
                        $"[AI Images] generatedImage is now set: {generatedImage != null}, size: {generatedImage.width}x{generatedImage.height}"
                    );
                }
                else
                {
                    DebugLogger.Warning(
                        $"[AI Images] Failed to load portrait texture for {pawn?.Name}"
                    );
                }
            }
            else
            {
                DebugLogger.Log($"[AI Images] No saved portrait found for {pawn?.Name}");
            }
        }

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

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

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

        /// <summary>
        /// Обновляет текущую пешку в окне
        /// </summary>
        public void UpdatePawn(Pawn newPawn)
        {
            DebugLogger.Log(
                $"[AI Images] UpdatePawn called - switching from {pawn?.Name} to {newPawn?.Name}"
            );

            this.pawn = newPawn;

            // Очищаем старое изображение при смене персонажа
            generatedImage = null;
            generationStatus = "";
            generationProgress = 0.0;
            currentStep = 0;
            totalSteps = 0;
            etaSeconds = 0.0;

            DebugLogger.Log($"[AI Images] Cleared generated image for {newPawn?.Name}");

            // Сбрасываем состояние сворачиваемых секций
            showPositivePrompt = false;
            showNegativePrompt = false;

            // Обновляем данные персонажа (включая загрузку портрета)
            RefreshPawnData();

            // Принудительно обновляем окно
            this.windowRect = new Rect(
                this.windowRect.x,
                this.windowRect.y,
                this.InitialSize.x,
                this.InitialSize.y
            );

            // Принудительно перерисовываем окно
            this.SetInitialSizeAndPosition();

            DebugLogger.Log($"[AI Images] UpdatePawn completed for {newPawn?.Name}");
        }

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

        /// <summary>
        /// Отладочный метод для проверки состояния всех пешек
        /// </summary>
        public static void DebugAllPawns()
        {
            DebugLogger.Log("[AI Images] === DEBUG: Checking all pawns ===");

            if (Current.Game?.Maps == null)
            {
                DebugLogger.Log("[AI Images] No game or maps available");
                return;
            }

            int totalPawns = 0;
            int pawnsWithComponents = 0;
            int pawnsWithPortraits = 0;

            foreach (var map in Current.Game.Maps)
            {
                foreach (var pawn in map.mapPawns.AllPawns)
                {
                    if (pawn.RaceProps?.Humanlike == true)
                    {
                        totalPawns++;
                        var (hasComponent, hasPortrait) = CheckPawnPortraitStatus(pawn);
                        if (hasComponent)
                            pawnsWithComponents++;
                        if (hasPortrait)
                            pawnsWithPortraits++;
                    }
                }
            }

            LogDebugSummary(totalPawns, pawnsWithComponents, pawnsWithPortraits);
        }

        private static (bool hasComponent, bool hasPortrait) CheckPawnPortraitStatus(Pawn pawn)
        {
            var comp = PawnPortraitHelper.GetPortraitComp(pawn);
            if (comp != null)
            {
                if (comp.HasPortrait)
                {
                    DebugLogger.Log(
                        $"[AI Images] {pawn.Name}: Has component with portrait '{comp.PortraitPath}'"
                    );
                    return (true, true);
                }
                else
                {
                    DebugLogger.Log($"[AI Images] {pawn.Name}: Has component but no portrait");
                    return (true, false);
                }
            }
            else
            {
                DebugLogger.Warning($"[AI Images] {pawn.Name}: No portrait component found!");
                return (false, false);
            }
        }

        private static void LogDebugSummary(
            int totalPawns,
            int pawnsWithComponents,
            int pawnsWithPortraits
        )
        {
            DebugLogger.Log($"[AI Images] === DEBUG SUMMARY ===");
            DebugLogger.Log($"[AI Images] Total humanlike pawns: {totalPawns}");
            DebugLogger.Log($"[AI Images] Pawns with components: {pawnsWithComponents}");
            DebugLogger.Log($"[AI Images] Pawns with portraits: {pawnsWithPortraits}");
            DebugLogger.Log($"[AI Images] === END DEBUG ===");
        }

        /// <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();
            generationProgress = 0.0;
            currentStep = 0;
            totalSteps = generationSettings.Steps;

            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,
                    SaveImagesToServer = AIImagesMod.Settings.saveImagesToServer,
                };

                // Создаем отдельный CancellationTokenSource для мониторинга прогресса
                var progressCts = new CancellationTokenSource();
                var progressTask = MonitorProgressAsync(progressCts.Token);

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

                // Останавливаем мониторинг прогресса
                progressCts.Cancel();
                try
                {
                    await progressTask;
                }
                catch (OperationCanceledException)
                {
                    // Ожидаемое исключение при остановке мониторинга
                }
                finally
                {
                    progressCts.Dispose();
                }

                if (result.Success)
                {
                    DebugLogger.Log($"[AI Images] Generation successful for {pawn?.Name}");
                    DebugLogger.Log(
                        $"[AI Images] Image data size: {result.ImageData?.Length ?? 0} bytes"
                    );
                    DebugLogger.Log($"[AI Images] Saved path: {result.SavedPath}");

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

                    // Сохраняем путь к портрету на персонаже
                    DebugLogger.Log(
                        $"[AI Images] About to save portrait path for {pawn?.Name}: {result.SavedPath}"
                    );
                    PawnPortraitHelper.SavePortraitPath(pawn, result.SavedPath);

                    Messages.Message(
                        "AIImages.Generation.SavedTo".Translate(result.SavedPath),
                        MessageTypeDefOf.PositiveEvent
                    );

                    DebugLogger.Log(
                        $"[AI Images] Portrait generation and saving completed for {pawn?.Name}"
                    );
                }
                else
                {
                    generationStatus =
                        $"AIImages.Generation.Failed".Translate() + ": {result.ErrorMessage}";
                    Messages.Message(generationStatus, MessageTypeDefOf.RejectInput);
                }
            }
            catch (OperationCanceledException)
            {
                generationStatus = "AIImages.Generation.Cancelled".Translate();
                DebugLogger.Log("[AI Images] Generation cancelled by user");
            }
            catch (Exception ex)
            {
                generationStatus = $"Error: {ex.Message}";
                DebugLogger.Error($"[AI Images] Generation error: {ex}");
                Messages.Message(
                    $"AIImages.Generation.Error".Translate() + ": {ex.Message}",
                    MessageTypeDefOf.RejectInput
                );
            }
            finally
            {
                isGenerating = false;
            }
        }

        /// <summary>
        /// Мониторит прогресс генерации и обновляет UI
        /// </summary>
        private async System.Threading.Tasks.Task MonitorProgressAsync(
            CancellationToken cancellationToken
        )
        {
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    var progress = await apiService.GetProgressAsync(cancellationToken);

                    if (progress != null && progress.IsActive)
                    {
                        generationProgress = progress.Progress;
                        currentStep = progress.CurrentStep;
                        totalSteps = progress.TotalSteps;
                        etaSeconds = progress.EtaRelative;

                        DebugLogger.Log(
                            $"[AI Images] Progress: {progress.Progress:P} - Step {progress.CurrentStep}/{progress.TotalSteps} - ETA: {progress.EtaRelative:F1}s"
                        );
                    }

                    // Обновляем каждые 500ms
                    await System.Threading.Tasks.Task.Delay(500, cancellationToken);
                }
            }
            catch (OperationCanceledException)
            {
                // Ожидаемое исключение при остановке
            }
            catch (Exception ex)
            {
                DebugLogger.Warning($"[AI Images] Progress monitoring error: {ex.Message}");
            }
        }

        /// <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 totalContentHeight = CalculateTotalContentHeight();
            Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, totalContentHeight);

            Widgets.BeginScrollView(inRect, ref mainScrollPosition, viewRect);

            float curY = 0f;

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

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

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

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

            // Определяем высоту колонок (берем большую из двух)
            float columnHeight = Mathf.Max(CalculateContentHeight(), CalculateRightColumnHeight());

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

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

            Widgets.EndScrollView();
        }

        private void DrawLeftColumn(Rect rect)
        {
            float contentY = rect.y;

            // Портрет персонажа (если есть)
            if (generatedImage != null)
            {
                float portraitSize = Mathf.Min(rect.width, 250f);
                Rect portraitRect = new Rect(
                    rect.x + (rect.width - portraitSize) / 2f,
                    contentY,
                    portraitSize,
                    portraitSize
                );

                // Рамка вокруг портрета
                Widgets.DrawBox(portraitRect);
                GUI.DrawTexture(portraitRect.ContractedBy(2f), generatedImage);
                contentY += portraitSize + 15f;
            }

            // Заголовок секции
            Text.Font = GameFont.Medium;
            Widgets.Label(
                new Rect(rect.x, contentY, rect.width, 30f),
                "AIImages.CharacterInfo.Title".Translate()
            );
            contentY += 35f;

            // Разделитель
            Widgets.DrawLineHorizontal(rect.x, contentY, rect.width);
            contentY += 10f;

            // Информация о персонаже
            DrawCharacterInfoContent(rect, contentY);
        }

        /// <summary>
        /// Отрисовывает информацию о персонаже в компактном виде
        /// </summary>
        private void DrawCharacterInfoContent(Rect parentRect, float startY)
        {
            float contentY = startY;
            float lineHeight = 22f;

            contentY = DrawBasicInfo(parentRect, contentY, lineHeight);
            contentY = DrawTraits(parentRect, contentY, lineHeight);
            contentY = DrawGenes(parentRect, contentY, lineHeight);
            contentY = DrawHediffs(parentRect, contentY, lineHeight);
            DrawApparel(parentRect, contentY, lineHeight);
        }

        /// <summary>
        /// Отрисовывает базовую информацию о персонаже
        /// </summary>
        private float DrawBasicInfo(Rect parentRect, float startY, float lineHeight)
        {
            float contentY = startY;
            float labelWidth = parentRect.width * 0.45f;
            float valueWidth = parentRect.width * 0.50f;

            Text.Font = GameFont.Tiny;

            var info = new[]
            {
                ("AIImages.Info.Gender".Translate(), appearanceData.Gender.ToString()),
                ("AIImages.Info.Age".Translate(), appearanceData.Age.ToString()),
                ("AIImages.Info.BodyType".Translate(), appearanceData.BodyType),
                (
                    "AIImages.Info.SkinTone".Translate(),
                    ColorDescriptionService.GetSkinToneDescription(pawn)
                ),
                ("AIImages.Info.Hair".Translate(), appearanceData.HairStyle),
                (
                    "AIImages.Info.HairColor".Translate(),
                    ColorDescriptionService.GetHairColorDescription(appearanceData.HairColor)
                ),
            };

            foreach (var (label, value) in info)
            {
                // Подсветка строк через одну
                var infoArray = info.ToArray();
                int index = Array.IndexOf(infoArray, (label, value));
                if ((index % 2) == 0)
                {
                    Widgets.DrawBoxSolid(
                        new Rect(parentRect.x, contentY, parentRect.width, lineHeight),
                        new Color(0.15f, 0.15f, 0.15f, 0.3f)
                    );
                }

                Widgets.Label(
                    new Rect(parentRect.x + 5f, contentY, labelWidth, lineHeight),
                    label + ":"
                );
                Widgets.Label(
                    new Rect(parentRect.x + labelWidth + 10f, contentY, valueWidth, lineHeight),
                    value
                );
                contentY += lineHeight;
            }

            return contentY;
        }

        /// <summary>
        /// Отрисовывает черты характера персонажа
        /// </summary>
        private float DrawTraits(Rect parentRect, float startY, float lineHeight)
        {
            float contentY = startY;

            if (pawn.story?.traits?.allTraits == null || !pawn.story.traits.allTraits.Any())
                return contentY;

            contentY += 15f;
            Text.Font = GameFont.Small;
            Widgets.Label(
                new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
                "AIImages.Info.Traits".Translate() + ":"
            );
            contentY += lineHeight + 2f;

            Text.Font = GameFont.Tiny;
            var traitLabels = pawn.story.traits.allTraits.Select(trait => trait.LabelCap);
            foreach (var traitLabel in traitLabels)
            {
                Widgets.Label(
                    new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
                    "• " + traitLabel
                );
                contentY += lineHeight;
            }

            return contentY;
        }

        /// <summary>
        /// Отрисовывает гены персонажа
        /// </summary>
        private float DrawGenes(Rect parentRect, float startY, float lineHeight)
        {
            float contentY = startY;

            if (pawn.genes?.GenesListForReading == null || !pawn.genes.GenesListForReading.Any())
                return contentY;

            contentY += 15f;
            Text.Font = GameFont.Small;
            Widgets.Label(
                new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
                "AIImages.Info.Genes".Translate() + ":"
            );
            contentY += lineHeight + 2f;

            Text.Font = GameFont.Tiny;
            var activeGenes = pawn.genes.GenesListForReading.Where(gene => gene.Active).ToList();
            foreach (var gene in activeGenes)
            {
                string geneInfo = BuildGeneInfo(gene);
                float textHeight = Text.CalcHeight(geneInfo, parentRect.width - 25f);

                Widgets.Label(
                    new Rect(parentRect.x + 15f, contentY, parentRect.width - 25f, textHeight),
                    "• " + geneInfo
                );
                contentY += textHeight;
            }

            return contentY;
        }

        /// <summary>
        /// Строит информационную строку для гена
        /// </summary>
        private string BuildGeneInfo(Gene gene)
        {
            string geneLabel = gene.Label ?? gene.def.LabelCap;
            string geneInfo = geneLabel;

            if (!string.IsNullOrEmpty(gene.def.description))
            {
                string description = gene.def.description;
                if (description.Length > 200)
                {
                    description = description.Substring(0, 197) + "...";
                }
                geneInfo += " - " + description;
            }

            return geneInfo;
        }

        /// <summary>
        /// Отрисовывает хедифы (состояния здоровья) персонажа
        /// </summary>
        private float DrawHediffs(Rect parentRect, float startY, float lineHeight)
        {
            float contentY = startY;

            if (pawn.health?.hediffSet?.hediffs == null || !pawn.health.hediffSet.hediffs.Any())
                return contentY;

            contentY += 15f;
            Text.Font = GameFont.Small;
            Widgets.Label(
                new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
                "AIImages.Info.Hediffs".Translate() + ":"
            );
            contentY += lineHeight + 2f;

            Text.Font = GameFont.Tiny;
            var hediffLabels = pawn
                .health.hediffSet.hediffs.Where(hediff => hediff.Visible)
                .Select(hediff => hediff.LabelCap);
            foreach (var hediffLabel in hediffLabels)
            {
                Widgets.Label(
                    new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
                    "• " + hediffLabel
                );
                contentY += lineHeight;
            }

            return contentY;
        }

        /// <summary>
        /// Отрисовывает одежду персонажа
        /// </summary>
        private void DrawApparel(Rect parentRect, float startY, float lineHeight)
        {
            float contentY = startY;
            var apparel = pawn.apparel?.WornApparel;

            if (apparel == null || !apparel.Any())
                return;

            contentY += 15f;
            Text.Font = GameFont.Small;
            Widgets.Label(
                new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
                "AIImages.Info.Apparel".Translate() + ":"
            );
            contentY += lineHeight + 2f;

            Text.Font = GameFont.Tiny;
            foreach (var item in apparel)
            {
                var colorDesc = ColorDescriptionService.GetApparelColorDescription(item.DrawColor);
                string apparelLabel = $"• {colorDesc} {item.def.label}";
                float apparelHeight = Text.CalcHeight(apparelLabel, parentRect.width - 25f);
                Widgets.Label(
                    new Rect(parentRect.x + 15f, contentY, parentRect.width - 25f, apparelHeight),
                    apparelLabel
                );
                contentY += apparelHeight;
            }
        }

        private void DrawRightColumn(Rect rect)
        {
            float curY = rect.y;

            curY = DrawImageTypeSelector(rect, curY);
            curY = DrawImagePreview(rect, curY);
            curY = DrawGenerationStatus(rect, curY);
            curY = DrawProgressBar(rect, curY);
            curY = DrawGenerationButton(rect, curY);

            // Сворачиваемая секция с позитивным промптом
            curY = DrawPromptSection(
                rect,
                curY,
                "AIImages.Prompt.PositiveTitle".Translate(),
                ref showPositivePrompt,
                () =>
                    promptGeneratorService.GeneratePositivePrompt(
                        appearanceData,
                        generationSettings
                    ),
                new Color(0.1f, 0.3f, 0.1f, 0.5f),
                ref promptScrollPosition
            );

            curY += 5f;

            // Сворачиваемая секция с негативным промптом
            curY = DrawPromptSection(
                rect,
                curY,
                "AIImages.Prompt.NegativeTitle".Translate(),
                ref showNegativePrompt,
                () => promptGeneratorService.GenerateNegativePrompt(generationSettings),
                new Color(0.3f, 0.1f, 0.1f, 0.5f),
                ref negativePromptScrollPosition
            );

            curY += 10f;

            // Кнопка обновления данных
            if (
                Widgets.ButtonText(
                    new Rect(rect.x, curY, rect.width, 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, curY, rect.width, 25f),
                    "AIImages.Prompt.Copied".Translate()
                );
                GUI.color = Color.white;
            }
        }

        private float CalculateContentHeight()
        {
            float height = CalculatePortraitHeight();
            height += CalculateBasicInfoHeight();
            height += CalculateTraitsHeight();
            height += CalculateGenesHeight();
            height += CalculateHediffsHeight();
            height += CalculateApparelHeight();
            height += 50f; // Дополнительный отступ
            return height;
        }

        /// <summary>
        /// Рассчитывает высоту портрета персонажа
        /// </summary>
        private float CalculatePortraitHeight()
        {
            if (generatedImage != null)
            {
                float portraitSize = 250f; // Максимальный размер портрета
                return portraitSize + 15f;
            }
            return 0f;
        }

        /// <summary>
        /// Рассчитывает высоту базовой информации
        /// </summary>
        private float CalculateBasicInfoHeight()
        {
            float height = 35f; // Заголовок "Информация о персонаже"
            height += 10f; // Разделитель
            height += 6 * 22f; // Базовая информация (6 строк по 22px)
            return height;
        }

        /// <summary>
        /// Рассчитывает высоту секции черт характера
        /// </summary>
        private float CalculateTraitsHeight()
        {
            if (pawn.story?.traits?.allTraits == null || !pawn.story.traits.allTraits.Any())
                return 0f;

            float height = 15f; // Отступ
            height += 22f; // Заголовок "Черты характера"
            height += 2f; // Отступ
            height += pawn.story.traits.allTraits.Count * 22f; // Каждая черта
            return height;
        }

        /// <summary>
        /// Рассчитывает высоту секции генов
        /// </summary>
        private float CalculateGenesHeight()
        {
            if (pawn.genes?.GenesListForReading == null || !pawn.genes.GenesListForReading.Any())
                return 0f;

            float height = 15f; // Отступ
            height += 22f; // Заголовок "Гены"
            height += 2f; // Отступ

            // Рассчитываем высоту для каждого гена с учетом описания
            Text.Font = GameFont.Tiny;
            var activeGenes = pawn.genes.GenesListForReading.Where(gene => gene.Active).ToList();
            float approximateColumnWidth = 900f * 0.35f; // Примерная ширина левой колонки
            float labelWidth = approximateColumnWidth - 25f;

            foreach (var gene in activeGenes)
            {
                string geneInfo = BuildGeneInfo(gene);
                height += Text.CalcHeight("• " + geneInfo, labelWidth);
            }

            return height;
        }

        /// <summary>
        /// Рассчитывает высоту секции хедифов
        /// </summary>
        private float CalculateHediffsHeight()
        {
            if (pawn.health?.hediffSet?.hediffs == null || !pawn.health.hediffSet.hediffs.Any())
                return 0f;

            float height = 15f; // Отступ
            height += 22f; // Заголовок "Хедифы"
            height += 2f; // Отступ
            height += pawn.health.hediffSet.hediffs.Count(hediff => hediff.Visible) * 22f; // Каждый видимый хедиф
            return height;
        }

        /// <summary>
        /// Рассчитывает высоту секции одежды
        /// </summary>
        private float CalculateApparelHeight()
        {
            var apparel = pawn.apparel?.WornApparel;
            if (apparel == null || !apparel.Any())
                return 0f;

            float height = 15f; // Отступ
            height += 22f; // Заголовок "Одежда"
            height += 2f; // Отступ
            height += apparel.Count * 26f; // Примерно по 22-30px на предмет одежды
            return height;
        }

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

            // Превью изображения
            if (generatedImage != null)
            {
                height += 410f; // 400f изображение + 10f отступ
            }
            else if (!isGenerating)
            {
                height += 310f; // 300f placeholder + 10f отступ
            }

            // Статус генерации
            if (!string.IsNullOrEmpty(generationStatus))
            {
                height += 30f;
            }

            // Прогресс бар
            if (isGenerating && generationProgress > 0.0)
            {
                height += 30f;
            }

            // Кнопка генерации
            height += 40f;

            // Позитивный промпт
            height += 36f; // Заголовок (32f + 4f отступ)
            if (showPositivePrompt)
            {
                height += 140f; // Бокс развернут (120f + 10f отступ + запас)
            }
            height += 5f; // Отступ между промптами

            // Негативный промпт
            height += 36f; // Заголовок (32f + 4f отступ)
            if (showNegativePrompt)
            {
                height += 140f; // Бокс развернут (120f + 10f отступ + запас)
            }
            height += 10f; // Отступ после промптов

            // Кнопка обновления
            height += 40f; // Увеличено с 35f до 40f

            // Сообщение о копировании
            if (copiedMessageTime > 0f)
            {
                height += 40f;
            }

            return height + 100f; // Увеличен дополнительный отступ снизу
        }

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

            // Заголовок и имя пешки
            height += 45f + 40f;

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

            // Высота колонок (берем большую)
            float columnHeight = Mathf.Max(CalculateContentHeight(), CalculateRightColumnHeight());
            height += columnHeight;

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

            return height;
        }

        /// <summary>
        /// /// Отрисовывает секцию с промптом
        /// </summary>
        private float DrawPromptSection(
            Rect parentRect,
            float startY,
            string title,
            ref bool expanded,
            System.Func<string> getPromptFunc,
            Color backgroundColor,
            ref Vector2 scrollPosition
        )
        {
            float curY = startY;
            float headerHeight = 32f;

            // Получаем промпт
            string prompt = getPromptFunc();

            // Рисуем заголовок с фоном
            Rect headerRect = new Rect(parentRect.x, curY, parentRect.width, headerHeight);
            Widgets.DrawBoxSolid(headerRect, new Color(0.25f, 0.25f, 0.25f, 0.8f));
            Widgets.DrawBox(headerRect);

            // Иконка раскрытия
            string icon = expanded ? "▼" : "►";
            Text.Font = GameFont.Small;
            Widgets.Label(new Rect(parentRect.x + 8f, curY + 6f, 20f, headerHeight), icon);

            // Заголовок
            Widgets.Label(
                new Rect(parentRect.x + 30f, curY + 6f, parentRect.width - 110f, headerHeight),
                title
            );

            // Кнопка копирования в заголовке (увеличена ширина)
            Rect copyButtonRect = new Rect(
                parentRect.x + parentRect.width - 100f,
                curY + 4f,
                95f,
                24f
            );
            if (Widgets.ButtonText(copyButtonRect, "📋 " + "AIImages.Copy".Translate()))
            {
                GUIUtility.systemCopyBuffer = prompt;
                copiedMessageTime = 2f;
            }

            // Клик на остальной области для раскрытия/сворачивания
            Rect clickableHeaderRect = new Rect(
                parentRect.x,
                curY,
                parentRect.width - 105f,
                headerHeight
            );
            if (Widgets.ButtonInvisible(clickableHeaderRect))
            {
                expanded = !expanded;
            }

            curY += headerHeight + 4f;

            // Рисуем содержимое если развернуто
            if (expanded)
            {
                float promptBoxHeight = 120f;
                Text.Font = GameFont.Tiny;
                float actualPromptHeight = Text.CalcHeight(prompt, parentRect.width - 20f);

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

                // Рисуем фон
                Widgets.DrawBoxSolid(promptOuterRect, backgroundColor);
                Widgets.DrawBox(promptOuterRect);

                // Рисуем промпт с прокруткой
                Widgets.BeginScrollView(
                    promptOuterRect.ContractedBy(5f),
                    ref scrollPosition,
                    promptViewRect
                );

                var prevAnchor = Text.Anchor;
                Text.Anchor = TextAnchor.UpperLeft;
                Text.WordWrap = true;

                Widgets.Label(
                    new Rect(0f, 0f, promptViewRect.width, promptViewRect.height),
                    prompt
                );

                Text.Anchor = prevAnchor;
                Text.WordWrap = true;

                Widgets.EndScrollView();

                curY += promptBoxHeight + 10f;
            }

            return curY;
        }

        /// <summary>
        /// Отрисовывает селектор типа изображения (портрет/полное тело)
        /// </summary>
        private float DrawImageTypeSelector(Rect rect, float curY)
        {
            Text.Font = GameFont.Small;
            float selectorHeight = 30f;

            // Заголовок
            Widgets.Label(
                new Rect(rect.x, curY, rect.width * 0.4f, selectorHeight),
                "AIImages.ImageType.Label".Translate() + ":"
            );

            // Радио-кнопки для выбора типа
            float radioX = rect.x + rect.width * 0.45f;
            float radioWidth = rect.width * 0.25f;
            float radioSpacing = 5f;

            // Портрет
            Rect portraitRect = new Rect(radioX, curY + 2f, radioWidth, selectorHeight - 4f);
            bool isPortrait = generationSettings.ImageType == Models.ImageType.Portrait;
            if (
                Widgets.RadioButtonLabeled(
                    portraitRect,
                    "AIImages.ImageType.Portrait".Translate(),
                    isPortrait
                ) && !isPortrait
            )
            {
                generationSettings.ImageType = Models.ImageType.Portrait;
                // Обновляем настройки в глобальных настройках
                AIImagesMod.Settings.imageType = Models.ImageType.Portrait;
                // При смене на портрет, можно изменить размеры на более квадратные
                if (generationSettings.Width > generationSettings.Height)
                {
                    generationSettings.Height = generationSettings.Width;
                }
            }

            // Полное тело
            Rect fullBodyRect = new Rect(
                radioX + radioWidth + radioSpacing,
                curY + 2f,
                radioWidth,
                selectorHeight - 4f
            );
            bool isFullBody = generationSettings.ImageType == Models.ImageType.FullBody;
            if (
                Widgets.RadioButtonLabeled(
                    fullBodyRect,
                    "AIImages.ImageType.FullBody".Translate(),
                    isFullBody
                ) && !isFullBody
            )
            {
                generationSettings.ImageType = Models.ImageType.FullBody;
                // Обновляем настройки в глобальных настройках
                AIImagesMod.Settings.imageType = Models.ImageType.FullBody;
                // При смене на полное тело, можно увеличить высоту
                if (generationSettings.Width >= generationSettings.Height)
                {
                    generationSettings.Height = (int)(generationSettings.Width * 1.5f);
                }
            }

            return curY + selectorHeight + 10f;
        }

        private float DrawImagePreview(Rect rect, float curY)
        {
            if (generatedImage != null)
            {
                float imageSize = Mathf.Min(rect.width, 400f);
                Rect imageRect = new Rect(
                    rect.x + (rect.width - imageSize) / 2f,
                    curY,
                    imageSize,
                    imageSize
                );
                GUI.DrawTexture(imageRect, generatedImage);
                return curY + imageSize + 10f;
            }

            float placeholderSize = Mathf.Min(rect.width, 300f);
            Rect placeholderRect = new Rect(
                rect.x + (rect.width - placeholderSize) / 2f,
                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;
            return curY + placeholderSize + 10f;
        }

        private float DrawGenerationStatus(Rect rect, float curY)
        {
            if (string.IsNullOrEmpty(generationStatus))
                return curY;

            Text.Font = GameFont.Small;
            float statusHeight = Text.CalcHeight(generationStatus, rect.width);
            Widgets.Label(new Rect(rect.x, curY, rect.width, statusHeight), generationStatus);
            return curY + statusHeight + 10f;
        }

        private float DrawProgressBar(Rect rect, float curY)
        {
            if (!isGenerating || generationProgress <= 0.0)
                return curY;

            Rect progressBarRect = new Rect(rect.x, curY, rect.width, 24f);

            string progressText;
            if (totalSteps > 0)
            {
                progressText =
                    $"{(generationProgress * 100):F1}% - Step {currentStep}/{totalSteps}";
                if (etaSeconds > 0)
                {
                    progressText += $" - ETA: {etaSeconds:F0}s";
                }
            }
            else
            {
                progressText = $"{(generationProgress * 100):F1}%";
            }

            Widgets.FillableBar(progressBarRect, (float)generationProgress);
            Text.Font = GameFont.Tiny;
            Text.Anchor = TextAnchor.MiddleCenter;
            Widgets.Label(progressBarRect, progressText);
            Text.Anchor = TextAnchor.UpperLeft;
            return curY + 30f;
        }

        private float DrawGenerationButton(Rect rect, float curY)
        {
            Text.Font = GameFont.Small;
            string buttonLabel = isGenerating
                ? "AIImages.Generation.Cancel".Translate()
                : "AIImages.Generation.Generate".Translate();

            // Основная кнопка генерации (занимает 40% ширины)
            float buttonWidth = rect.width * 0.4f;
            if (Widgets.ButtonText(new Rect(rect.x, curY, buttonWidth, 35f), buttonLabel))
            {
                if (isGenerating)
                    CancelGeneration();
                else
                    StartGeneration();
            }

            // Кнопка галереи
            float galleryButtonWidth = rect.width * 0.35f;
            float galleryButtonX = rect.x + buttonWidth + 10f;
            int imageCount = PawnPortraitHelper.GetPortraitCount(pawn);
            string galleryLabel = "AIImages.Gallery.OpenGallery".Translate();
            if (imageCount > 0)
            {
                galleryLabel += " " + "AIImages.Gallery.ImagesCount".Translate(imageCount);
            }

            if (Widgets.ButtonText(new Rect(galleryButtonX, curY, galleryButtonWidth, 35f), galleryLabel))
            {
                var galleryWindow = new Window_AIGallery(pawn);
                Find.WindowStack.Add(galleryWindow);
            }

            // Отладочная кнопка (занимает 20% ширины)
            float debugButtonWidth = rect.width * 0.2f;
            float debugButtonX = galleryButtonX + galleryButtonWidth + 10f;
            if (Widgets.ButtonText(new Rect(debugButtonX, curY, debugButtonWidth, 35f), "Debug"))
            {
                DebugAllPawns();
            }

            return curY + 40f;
        }
    }
}
