using System.Collections.Generic;
using System.Linq;
using System.Text;
using AIImages.Models;
using RimWorld;
using Verse;

namespace AIImages.Services
{
    /// <summary>
    /// Продвинутый генератор промптов для Stable Diffusion
    /// </summary>
    public class AdvancedPromptGenerator : IPromptGeneratorService
    {
        private static readonly Dictionary<string, string> TraitToMood = new Dictionary<
            string,
            string
        >
        {
            { "Kind", "warm smile, gentle expression, friendly eyes" },
            { "Bloodlust", "intense gaze, fierce expression, aggressive posture" },
            { "Psychopath", "cold eyes, emotionless face, calculating expression" },
            { "Pessimist", "sad eyes, worried expression, downcast gaze" },
            { "Optimist", "bright smile, hopeful expression, cheerful demeanor" },
            { "Nervous", "anxious expression, tense posture, worried eyes" },
            { "Careful", "focused expression, attentive gaze, composed posture" },
            { "Brave", "confident expression, determined gaze, strong posture" },
            { "Wimp", "fearful eyes, nervous expression, timid posture" },
            { "Greedy", "cunning expression, calculating eyes, sly smile" },
            { "Jealous", "envious gaze, bitter expression, tense face" },
            { "Ascetic", "serene expression, calm demeanor, peaceful eyes" },
            { "Beautiful", "stunning features, attractive appearance, graceful" },
            { "Ugly", "rough features, weathered appearance" },
            { "Pretty", "attractive features, pleasant appearance, charming" },
        };

        private static readonly Dictionary<ArtStyle, string> ArtStylePrompts = new Dictionary<
            ArtStyle,
            string
        >
        {
            { ArtStyle.None, "" },
            { ArtStyle.Realistic, "photorealistic, hyperrealistic, realistic photo, photography" },
            { ArtStyle.SemiRealistic, "semi-realistic, detailed illustration, realistic art" },
            { ArtStyle.Anime, "anime style, manga style, anime character" },
            {
                ArtStyle.ConceptArt,
                "concept art, digital art, artstation, professional concept design"
            },
            { ArtStyle.DigitalPainting, "digital painting, painterly, brush strokes, artistic" },
            { ArtStyle.OilPainting, "oil painting, traditional painting, canvas, fine art" },
            { ArtStyle.Sketch, "pencil sketch, hand drawn, sketch art, line art" },
            { ArtStyle.CellShaded, "cell shaded, flat colors, toon shading, stylized" },
        };

        public string GeneratePositivePrompt(
            PawnAppearanceData appearanceData,
            StableDiffusionSettings settings
        )
        {
            if (appearanceData == null)
                return "portrait of a person";

            StringBuilder prompt = new StringBuilder();

            // 1. Базовый пользовательский промпт (если указан) - идет первым
            if (!string.IsNullOrEmpty(settings.PositivePrompt))
            {
                prompt.Append(settings.PositivePrompt);
                prompt.Append(", ");
            }

            // 2. Художественный стиль
            if (
                ArtStylePrompts.TryGetValue(settings.ArtStyle, out string stylePrompt)
                && !string.IsNullOrEmpty(stylePrompt)
            )
            {
                prompt.Append(stylePrompt);
                prompt.Append(", ");
            }

            // 3. Тип кадра - автоматически добавляем "portrait" для генерации персонажей
            prompt.Append("portrait, head and shoulders of ");

            // 4. Базовое описание (возраст и пол)
            prompt.Append(GetAgeAndGenderDescription(appearanceData));
            prompt.Append(", ");

            // 5. Тип тела
            string bodyType = GetBodyTypeDescription(appearanceData.BodyType);
            if (!string.IsNullOrEmpty(bodyType))
            {
                prompt.Append(bodyType);
                prompt.Append(", ");
            }

            // 6. Цвет кожи
            string skinTone = ColorDescriptionService.GetSkinToneDescription(
                appearanceData.SkinColor
            );
            prompt.Append(skinTone);
            prompt.Append(", ");

            // 7. Волосы
            string hairDescription = GetHairDescription(appearanceData);
            if (!string.IsNullOrEmpty(hairDescription))
            {
                prompt.Append(hairDescription);
                prompt.Append(", ");
            }

            // 8. Настроение и выражение на основе черт характера
            string moodDescription = GetMoodFromTraits(appearanceData.Traits);
            if (!string.IsNullOrEmpty(moodDescription))
            {
                prompt.Append(moodDescription);
                prompt.Append(", ");
            }

            // 9. Одежда
            string apparelDescription = GetApparelDescription(appearanceData.Apparel);
            if (!string.IsNullOrEmpty(apparelDescription))
            {
                prompt.Append(apparelDescription);
                prompt.Append(", ");
            }

            // 10. Качественные теги
            prompt.Append(GetQualityTags(settings.ArtStyle));

            return prompt.ToString().Trim().TrimEnd(',');
        }

        public string GenerateNegativePrompt(StableDiffusionSettings settings)
        {
            StringBuilder negativePrompt = new StringBuilder();

            // 1. Пользовательский негативный промпт (если указан) - идет первым
            if (!string.IsNullOrEmpty(settings.NegativePrompt))
            {
                negativePrompt.Append(settings.NegativePrompt);
                negativePrompt.Append(", ");
            }

            // 2. Базовые негативные промпты
            negativePrompt.Append(
                "ugly, deformed, low quality, blurry, bad anatomy, worst quality, "
            );
            negativePrompt.Append(
                "mutated, disfigured, bad proportions, extra limbs, missing limbs, "
            );

            // 3. Специфичные для стиля негативы
            switch (settings.ArtStyle)
            {
                case ArtStyle.Realistic:
                case ArtStyle.SemiRealistic:
                    negativePrompt.Append("cartoon, anime, painting, drawing, illustration, ");
                    break;
                case ArtStyle.Anime:
                    negativePrompt.Append("realistic, photo, photography, 3d, ");
                    break;
                case ArtStyle.None:
                    // Без дополнительных негативных промптов для стиля None
                    break;
            }

            return negativePrompt.ToString().Trim().TrimEnd(',');
        }

        public string GetFullPromptDescription(
            PawnAppearanceData appearanceData,
            StableDiffusionSettings settings
        )
        {
            StringBuilder description = new StringBuilder();

            description.AppendLine("=== Positive Prompt ===");
            description.AppendLine(GeneratePositivePrompt(appearanceData, settings));
            description.AppendLine();

            description.AppendLine("=== Negative Prompt ===");
            description.AppendLine(GenerateNegativePrompt(settings));
            description.AppendLine();

            description.AppendLine("=== Technical Parameters ===");
            description.AppendLine($"Steps: {settings.Steps}");
            description.AppendLine($"CFG Scale: {settings.CfgScale}");
            description.AppendLine($"Size: {settings.Width}x{settings.Height}");
            description.AppendLine($"Sampler: {settings.Sampler}");
            description.AppendLine(
                $"Seed: {(settings.Seed == -1 ? "Random" : settings.Seed.ToString())}"
            );

            return description.ToString();
        }

        private string GetAgeAndGenderDescription(PawnAppearanceData data)
        {
            string ageGroup = data.Age switch
            {
                < 18 => "young",
                < 25 => "young adult",
                < 35 => "adult",
                < 50 => "middle-aged",
                < 65 => "mature",
                _ => "elderly",
            };

            string genderLabel = data.Gender switch
            {
                Gender.Male => "man",
                Gender.Female => "woman",
                _ => "person",
            };
            return $"{ageGroup} {genderLabel}";
        }

        private string GetBodyTypeDescription(string bodyType)
        {
            if (string.IsNullOrEmpty(bodyType))
                return "";

            return bodyType.ToLower() switch
            {
                "thin" => "slender build, lean physique",
                "hulk" => "muscular build, strong physique, athletic body",
                "fat" => "heavyset build, stocky physique",
                "female" => "feminine build",
                "male" => "masculine build",
                _ => "average build",
            };
        }

        private string GetHairDescription(PawnAppearanceData data)
        {
            if (string.IsNullOrEmpty(data.HairDefName))
                return "";

            StringBuilder hair = new StringBuilder();

            // Цвет волос
            string hairColor = ColorDescriptionService.GetHairColorDescription(data.HairColor);
            hair.Append(hairColor);
            hair.Append(" ");

            // Стиль прически - используем DefName для английского названия
            string style = CleanDefName(data.HairDefName)
                .Replace("shaved", "very short")
                .Replace("mohawk", "mohawk hairstyle");

            hair.Append(style);
            hair.Append(" hair");

            return hair.ToString();
        }

        private string GetMoodFromTraits(List<Trait> traits)
        {
            if (traits == null || !traits.Any())
                return "neutral expression";

            // Ищем черты, которые влияют на внешний вид
            foreach (var trait in traits)
            {
                string traitDefName = trait.def.defName;
                if (TraitToMood.TryGetValue(traitDefName, out string mood))
                {
                    return mood;
                }
            }

            return "calm expression";
        }

        private string GetApparelDescription(List<ApparelData> apparel)
        {
            if (apparel == null || !apparel.Any())
                return "simple clothes";

            StringBuilder apparelDesc = new StringBuilder("wearing ");

            // Берем топ 5 наиболее заметных предметов одежды
            var visibleApparel = apparel.Take(5).ToList();

            List<string> items = new List<string>();
            foreach (var item in visibleApparel)
            {
                StringBuilder itemDesc = new StringBuilder();

                // Цвет (если не белый)
                if (item.Color != UnityEngine.Color.white)
                {
                    string colorDesc = ColorDescriptionService.GetApparelColorDescription(
                        item.Color
                    );
                    itemDesc.Append(colorDesc);
                    itemDesc.Append(" ");
                }

                // Материал - используем DefName для английского названия
                if (!string.IsNullOrEmpty(item.MaterialDefName))
                {
                    itemDesc.Append(CleanDefName(item.MaterialDefName));
                    itemDesc.Append(" ");
                }

                // Название предмета - используем DefName для английского названия
                itemDesc.Append(CleanDefName(item.DefName));

                items.Add(itemDesc.ToString());
            }

            apparelDesc.Append(string.Join(", ", items));

            return apparelDesc.ToString();
        }

        private string GetQualityTags(ArtStyle style)
        {
            var baseTags = "highly detailed, professional, masterpiece, best quality";

            switch (style)
            {
                case ArtStyle.None:
                    return baseTags;
                case ArtStyle.Realistic:
                case ArtStyle.SemiRealistic:
                    return $"{baseTags}, professional photography, 8k uhd, dslr, high quality, sharp focus";
                case ArtStyle.Anime:
                    return $"{baseTags}, anime masterpiece, high resolution, vibrant colors";
                case ArtStyle.ConceptArt:
                    return $"{baseTags}, trending on artstation, professional digital art";
                default:
                    return baseTags;
            }
        }

        /// <summary>
        /// Преобразует defName в читаемый английский текст для промпта
        /// Пример: "Apparel_Pants" -> "pants", "Synthread" -> "synthread"
        /// </summary>
        private string CleanDefName(string defName)
        {
            if (string.IsNullOrEmpty(defName))
                return "";

            string cleaned = defName;

            // Убираем распространенные префиксы RimWorld
            cleaned = System.Text.RegularExpressions.Regex.Replace(
                cleaned,
                "^(Apparel_|Armor_|Weapon_|Thing_)",
                "",
                System.Text.RegularExpressions.RegexOptions.IgnoreCase
            );

            // Разделяем CamelCase на слова
            cleaned = System.Text.RegularExpressions.Regex.Replace(
                cleaned,
                "([a-z])([A-Z])",
                "$1 $2"
            );

            // Заменяем подчеркивания на пробелы
            cleaned = cleaned.Replace("_", " ");

            // Убираем множественные пробелы
            cleaned = System.Text.RegularExpressions.Regex.Replace(cleaned, @"\s+", " ");

            // Приводим к нижнему регистру и убираем лишние пробелы
            return cleaned.Trim().ToLower();
        }
    }
}
