using System;
using System.Collections.Generic;
using System.Linq;
using AIImages.Helpers;
using AIImages.Models;
using AIImages.Services;
using AIImages.Settings;
using RimWorld;
using UnityEngine;
using Verse;

namespace AIImages
{
    /// <summary>
    /// UI для настроек мода в меню настроек RimWorld
    /// </summary>
    public static class AIImagesSettingsUI
    {
        private static Vector2 scrollPosition = Vector2.zero;
        private static string stepsBuffer;
        private static string widthBuffer;
        private static string heightBuffer;

        public static void DoSettingsWindowContents(
            Rect inRect,
            AIImagesModSettings settings,
            ServiceContainer serviceContainer
        )
        {
            InitializeBuffers(settings);

            Listing_Standard listingStandard = new Listing_Standard();
            Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, 1250f);

            Widgets.BeginScrollView(inRect, ref scrollPosition, viewRect);
            listingStandard.Begin(viewRect);

            DrawApiSettings(listingStandard, settings, serviceContainer);
            DrawGenerationSettings(listingStandard, settings);
            DrawSamplerSchedulerSettings(listingStandard, settings);
            DrawPromptsSettings(listingStandard, settings);
            DrawOptionsSettings(listingStandard, settings);

            listingStandard.End();
            Widgets.EndScrollView();
        }

        private static void InitializeBuffers(AIImagesModSettings settings)
        {
            if (string.IsNullOrEmpty(stepsBuffer))
            {
                stepsBuffer = settings.steps.ToString();
                widthBuffer = settings.width.ToString();
                heightBuffer = settings.height.ToString();
            }
        }

        private static void DrawApiSettings(
            Listing_Standard listingStandard,
            AIImagesModSettings settings,
            ServiceContainer serviceContainer
        )
        {
            listingStandard.Label(
                "AIImages.Settings.ApiSection".Translate(),
                -1f,
                "AIImages.Settings.ApiSectionTooltip".Translate()
            );
            listingStandard.GapLine();

            string oldEndpoint = settings.apiEndpoint;
            listingStandard.Label("AIImages.Settings.ApiEndpoint".Translate() + ":");
            settings.apiEndpoint = listingStandard.TextEntry(settings.apiEndpoint);
            listingStandard.Gap(8f);

            // Если endpoint изменился, пересоздаем API сервис
            if (oldEndpoint != settings.apiEndpoint)
            {
                try
                {
                    serviceContainer.RecreateApiService();
                }
                catch (Exception ex)
                {
                    Log.Error($"[AI Images] Failed to recreate API service: {ex.Message}");
                    Messages.Message(
                        "Failed to update API endpoint. Check the log.",
                        MessageTypeDefOf.RejectInput
                    );
                }
            }

            if (listingStandard.ButtonText("AIImages.Settings.TestConnection".Translate()))
            {
                TestApiConnection(serviceContainer.ApiService, settings.apiEndpoint);
            }

            if (listingStandard.ButtonText("AIImages.Settings.LoadFromApi".Translate()))
            {
                LoadAllFromApi(serviceContainer.ApiService, settings);
            }

            DrawModelDropdown(listingStandard, settings);

            listingStandard.Gap(12f);
        }

        private static void DrawModelDropdown(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            if (
                listingStandard.ButtonTextLabeled(
                    "AIImages.Settings.Model".Translate(),
                    string.IsNullOrEmpty(settings.selectedModel)
                        ? "AIImages.Settings.NoModelSelected".Translate()
                        : settings.selectedModel
                )
            )
            {
                List<FloatMenuOption> modelOptions = new List<FloatMenuOption>();
                if (!settings.availableModels.Any())
                {
                    modelOptions.Add(
                        new FloatMenuOption("AIImages.Settings.LoadModelsFirst".Translate(), null)
                    );
                }
                else
                {
                    foreach (string model in settings.availableModels)
                    {
                        string localModel = model;
                        modelOptions.Add(
                            new FloatMenuOption(model, () => settings.selectedModel = localModel)
                        );
                    }
                }
                Find.WindowStack.Add(new FloatMenu(modelOptions));
            }
        }

        private static void DrawGenerationSettings(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            listingStandard.Label(
                "AIImages.Settings.GenerationSection".Translate(),
                -1f,
                "AIImages.Settings.GenerationSectionTooltip".Translate()
            );
            listingStandard.GapLine();

            DrawArtStyleDropdown(listingStandard, settings);
            listingStandard.Gap(8f);

            listingStandard.Label("AIImages.Settings.Steps".Translate() + $": {settings.steps}");
            settings.steps = (int)listingStandard.Slider(settings.steps, 1, 150);
            listingStandard.Gap(8f);

            listingStandard.Label(
                "AIImages.Settings.CfgScale".Translate() + $": {settings.cfgScale:F1}"
            );
            settings.cfgScale = listingStandard.Slider(settings.cfgScale, 1f, 30f);
            listingStandard.Gap(8f);

            DrawSizeSettings(listingStandard, settings);
            listingStandard.Gap(12f);
        }

        private static void DrawArtStyleDropdown(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            // Получаем текущий стиль
            var currentStyleDef = DefDatabase<ArtStyleDef>.GetNamedSilentFail(
                settings.artStyleDefName
            );
            string currentStyleLabel = currentStyleDef?.label ?? settings.artStyleDefName;

            if (
                listingStandard.ButtonTextLabeled(
                    "AIImages.Settings.ArtStyle".Translate(),
                    currentStyleLabel
                )
            )
            {
                List<FloatMenuOption> styleOptions = new List<FloatMenuOption>();

                // Получаем все стили из DefDatabase и сортируем по sortOrder
                var allStyles = DefDatabase<ArtStyleDef>.AllDefs.OrderBy(s => s.sortOrder);

                foreach (var styleDef in allStyles)
                {
                    string localDefName = styleDef.defName;
                    string localLabel = styleDef.label;

                    styleOptions.Add(
                        new FloatMenuOption(
                            localLabel,
                            () => settings.artStyleDefName = localDefName
                        )
                    );
                }

                Find.WindowStack.Add(new FloatMenu(styleOptions));
            }
        }

        private static void DrawSizeSettings(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            listingStandard.Label("AIImages.Settings.Width".Translate() + ":");
            widthBuffer = listingStandard.TextEntry(widthBuffer);
            if (int.TryParse(widthBuffer, out int width))
            {
                settings.width = Mathf.Clamp(width, 64, 2048);
            }

            listingStandard.Label("AIImages.Settings.Height".Translate() + ":");
            heightBuffer = listingStandard.TextEntry(heightBuffer);
            if (int.TryParse(heightBuffer, out int height))
            {
                settings.height = Mathf.Clamp(height, 64, 2048);
            }

            DrawSizePresets(listingStandard, settings);
        }

        private static void DrawSizePresets(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            // Получаем все предустановки размеров из DefDatabase
            var allPresets = DefDatabase<ImageSizePresetDef>
                .AllDefs.OrderBy(p => p.sortOrder)
                .ToList();

            if (!allPresets.Any())
            {
                return;
            }

            listingStandard.Gap(4f);

            // Разбиваем на строки по 3 кнопки
            int buttonsPerRow = 3;
            float buttonWidth = 80f;
            float spacing = 5f;

            for (int i = 0; i < allPresets.Count; i += buttonsPerRow)
            {
                Rect rowRect = listingStandard.GetRect(30f);

                for (int j = 0; j < buttonsPerRow && (i + j) < allPresets.Count; j++)
                {
                    var preset = allPresets[i + j];
                    float xOffset = j * (buttonWidth + spacing);

                    if (
                        Widgets.ButtonText(
                            new Rect(rowRect.x + xOffset, rowRect.y, buttonWidth, 30f),
                            preset.label
                        )
                    )
                    {
                        settings.width = preset.width;
                        settings.height = preset.height;
                        widthBuffer = preset.width.ToString();
                        heightBuffer = preset.height.ToString();
                    }
                }

                listingStandard.Gap(4f);
            }
        }

        private static void DrawSamplerSchedulerSettings(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            DrawSamplerDropdown(listingStandard, settings);
            DrawSchedulerDropdown(listingStandard, settings);
            listingStandard.Gap(12f);
        }

        private static void DrawSamplerDropdown(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            if (
                listingStandard.ButtonTextLabeled(
                    "AIImages.Settings.Sampler".Translate(),
                    settings.selectedSampler
                )
            )
            {
                List<FloatMenuOption> samplerOptions = new List<FloatMenuOption>();
                var availableSamplers = settings.availableSamplers.Any()
                    ? settings.availableSamplers
                    : new List<string> { settings.selectedSampler };

                foreach (string sampler in availableSamplers)
                {
                    string localSampler = sampler;
                    samplerOptions.Add(
                        new FloatMenuOption(sampler, () => settings.selectedSampler = localSampler)
                    );
                }
                Find.WindowStack.Add(new FloatMenu(samplerOptions));
            }
        }

        private static void DrawSchedulerDropdown(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            if (
                listingStandard.ButtonTextLabeled(
                    "AIImages.Settings.Scheduler".Translate(),
                    settings.selectedScheduler
                )
            )
            {
                List<FloatMenuOption> schedulerOptions = new List<FloatMenuOption>();
                var availableSchedulers = settings.availableSchedulers.Any()
                    ? settings.availableSchedulers
                    : new List<string> { settings.selectedScheduler };

                foreach (string scheduler in availableSchedulers)
                {
                    string localScheduler = scheduler;
                    schedulerOptions.Add(
                        new FloatMenuOption(
                            scheduler,
                            () => settings.selectedScheduler = localScheduler
                        )
                    );
                }
                Find.WindowStack.Add(new FloatMenu(schedulerOptions));
            }
        }

        private static void DrawPromptsSettings(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            listingStandard.Label(
                "AIImages.Settings.PromptsSection".Translate(),
                -1f,
                "AIImages.Settings.PromptsSectionTooltip".Translate()
            );
            listingStandard.GapLine();

            listingStandard.Label("AIImages.Settings.BasePositivePrompt".Translate() + ":");
            settings.basePositivePrompt = listingStandard.TextEntry(settings.basePositivePrompt, 3);
            listingStandard.Gap(8f);

            listingStandard.Label("AIImages.Settings.BaseNegativePrompt".Translate() + ":");
            settings.baseNegativePrompt = listingStandard.TextEntry(settings.baseNegativePrompt, 3);
            listingStandard.Gap(12f);
        }

        private static void DrawOptionsSettings(
            Listing_Standard listingStandard,
            AIImagesModSettings settings
        )
        {
            listingStandard.Label("AIImages.Settings.OptionsSection".Translate());
            listingStandard.GapLine();

            listingStandard.CheckboxLabeled(
                "AIImages.Settings.AutoLoadModels".Translate(),
                ref settings.autoLoadModels
            );
            listingStandard.CheckboxLabeled(
                "AIImages.Settings.ShowTechnicalInfo".Translate(),
                ref settings.showTechnicalInfo
            );
            listingStandard.CheckboxLabeled(
                "AIImages.Settings.SaveHistory".Translate(),
                ref settings.saveGenerationHistory
            );
            listingStandard.CheckboxLabeled(
                "AIImages.Settings.SaveImagesToServer".Translate(),
                ref settings.saveImagesToServer,
                "AIImages.Settings.SaveImagesToServerTooltip".Translate()
            );
            listingStandard.CheckboxLabeled(
                "AIImages.Settings.EnableDebugLogs".Translate(),
                ref settings.enableDebugLogs,
                "AIImages.Settings.EnableDebugLogsTooltip".Translate()
            );

            listingStandard.Gap(12f);

            listingStandard.Label("AIImages.Settings.SavePath".Translate() + ":");
            settings.savePath = listingStandard.TextEntry(settings.savePath);

            listingStandard.Gap(12f);

            // Кнопка очистки всех изображений
            if (listingStandard.ButtonText("AIImages.Settings.ClearAllImages".Translate()))
            {
                ClearAllGeneratedImages(settings);
            }
        }

        private static void TestApiConnection(
            IStableDiffusionApiService apiService,
            string endpoint
        )
        {
            _ = AsyncHelper.RunAsync(
                async () =>
                {
                    Log.Message($"[AI Images] Testing connection to {endpoint}...");
                    bool available = await apiService.CheckApiAvailability(endpoint);

                    if (available)
                    {
                        Messages.Message(
                            "AIImages.Settings.ConnectionSuccess".Translate(),
                            MessageTypeDefOf.PositiveEvent
                        );
                    }
                    else
                    {
                        Messages.Message(
                            "AIImages.Settings.ConnectionFailed".Translate(),
                            MessageTypeDefOf.RejectInput
                        );
                    }
                },
                "API Connection Test"
            );
        }

        private static void LoadAllFromApi(
            IStableDiffusionApiService apiService,
            AIImagesModSettings settings
        )
        {
            _ = AsyncHelper.RunAsync(
                async () =>
                {
                    Log.Message("[AI Images] Loading models, samplers and schedulers from API...");

                    // Загружаем модели
                    var models = await apiService.GetAvailableModels(settings.apiEndpoint);
                    settings.availableModels = models;

                    // Загружаем семплеры
                    var samplers = await apiService.GetAvailableSamplers(settings.apiEndpoint);
                    settings.availableSamplers = samplers;

                    // Загружаем schedulers
                    var schedulers = await apiService.GetAvailableSchedulers(settings.apiEndpoint);
                    settings.availableSchedulers = schedulers;

                    int totalCount = models.Count + samplers.Count + schedulers.Count;
                    if (totalCount > 0)
                    {
                        ShowSuccessMessage(models.Count, samplers.Count, schedulers.Count);
                        AutoSelectDefaults(settings, models, samplers, schedulers);
                    }
                    else
                    {
                        Messages.Message(
                            "AIImages.Settings.NothingLoaded".Translate(),
                            MessageTypeDefOf.RejectInput
                        );
                    }
                },
                "Load API Data"
            );
        }

        private static void ShowSuccessMessage(int modelCount, int samplerCount, int schedulerCount)
        {
            Messages.Message(
                "AIImages.Settings.AllLoaded".Translate(modelCount, samplerCount, schedulerCount),
                MessageTypeDefOf.PositiveEvent
            );
        }

        private static void AutoSelectDefaults(
            AIImagesModSettings settings,
            List<string> models,
            List<string> samplers,
            List<string> schedulers
        )
        {
            AutoSelectIfNeeded(ref settings.selectedModel, models, settings.selectedModel);
            AutoSelectIfNeeded(ref settings.selectedSampler, samplers, settings.selectedSampler);
            AutoSelectIfNeeded(
                ref settings.selectedScheduler,
                schedulers,
                settings.selectedScheduler
            );
        }

        private static void AutoSelectIfNeeded(
            ref string selectedValue,
            List<string> availableValues,
            string currentValue
        )
        {
            bool needsSelection =
                string.IsNullOrEmpty(currentValue) || !availableValues.Contains(currentValue);

            if (needsSelection && availableValues.Count > 0)
            {
                selectedValue = availableValues[0];
            }
        }

        private static void ClearAllGeneratedImages(AIImagesModSettings settings)
        {
            Find.WindowStack.Add(
                Dialog_MessageBox.CreateConfirmation(
                    "AIImages.Settings.ClearAllImagesConfirm".Translate(),
                    delegate
                    {
                        int deletedCount = PawnPortraitHelper.ClearAllPortraits(settings.savePath);
                        Messages.Message(
                            "AIImages.Settings.ClearAllImagesSuccess".Translate(deletedCount),
                            MessageTypeDefOf.PositiveEvent
                        );
                    },
                    destructive: true
                )
            );
        }
    }
}
