using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;

namespace AIImages.Services
{
    /// <summary>
    /// Сервис для умного определения цветов (вместо RGB значений)
    /// </summary>
    public static class ColorDescriptionService
    {
        /// <summary>
        /// Получает текстовое описание цвета волос
        /// </summary>
        public static string GetHairColorDescription(Color color)
        {
            float h,
                s,
                v;
            Color.RGBToHSV(color, out h, out s, out v);

            // Проверяем на оттенки серого
            if (s < 0.15f)
            {
                return GetGrayscaleDescription(v);
            }

            // Определяем оттенок
            string hueDescription = GetHueDescription(h);
            string brightnessModifier = GetBrightnessModifier(v, s);

            return $"{brightnessModifier}{hueDescription}".Trim();
        }

        /// <summary>
        /// Получает текстовое описание цвета кожи
        /// Сначала проверяет специальные гены цвета кожи (зелёная, синяя и т.д.),
        /// затем использует вычисленный RimWorld цвет кожи
        /// </summary>
        public static string GetSkinToneDescription(Pawn pawn)
        {
            if (pawn?.genes?.GenesListForReading == null)
                return GetSkinToneDescription(pawn.story.SkinColor);

            // Ищем активные гены цвета кожи (особенно специальные: зелёная, синяя, красная и т.д.)
            var skinColorGenes = pawn
                .genes.GenesListForReading.Where(gene =>
                    gene.Active && IsSpecialSkinColorGene(gene.def)
                )
                .ToList();

            // Если есть специальные гены цвета кожи, используем их описание
            if (skinColorGenes.Any())
            {
                var specialGene = skinColorGenes[0];
                string geneDescription = GetSpecialGeneSkinTone(specialGene.def.defName);
                if (!string.IsNullOrEmpty(geneDescription))
                    return geneDescription;
            }

            // Иначе RimWorld уже определил цвет текстуры пешки на основе генов (включая уровень мелатонина)
            // Используем этот вычисленный цвет
            return GetSkinToneDescription(pawn.story.SkinColor);
        }

        /// <summary>
        /// Проверяет, является ли ген специальным геном цвета кожи (зелёная, синяя, красная и т.д.)
        /// </summary>
        private static bool IsSpecialSkinColorGene(GeneDef geneDef)
        {
            if (geneDef == null)
                return false;

            string geneDefName = geneDef.defName;

            // Специальные цвета: зелёная, синяя, красная, жёлтая, фиолетовая, оранжевая, чёрная, белая, серая
            return geneDefName.StartsWith("Skin_")
                && (
                    geneDefName.Contains("Green")
                    || geneDefName.Contains("Blue")
                    || geneDefName.Contains("Red")
                    || geneDefName.Contains("Yellow")
                    || geneDefName.Contains("Purple")
                    || geneDefName.Contains("Orange")
                    || geneDefName.Contains("Black")
                    || geneDefName.Contains("White")
                    || geneDefName.Contains("Gray")
                    || geneDefName.Contains("Grey")
                    || geneDefName.Contains("Ink")
                    || geneDefName.Contains("Slate")
                    || geneDefName.Contains("Sheer")
                    || geneDefName.Contains("Pale")
                    || geneDefName.Contains("Deep")
                );
        }

        /// <summary>
        /// Получает описание для специальных генов цвета кожи
        /// </summary>
        private static string GetSpecialGeneSkinTone(string geneDefName)
        {
            switch (geneDefName)
            {
                case "Skin_InkBlack":
                    return "ink black skin";
                case "Skin_SlateGray":
                    return "slate gray skin";
                case "Skin_LightGray":
                    return "light gray skin";
                case "Skin_SheerWhite":
                    return "sheer white skin";
                case "Skin_Blue":
                    return "blue skin";
                case "Skin_Purple":
                    return "purple skin";
                case "Skin_PaleRed":
                    return "pale red skin";
                case "Skin_DeepRed":
                    return "deep red skin";
                case "Skin_PaleYellow":
                    return "pale yellow skin";
                case "Skin_DeepYellow":
                    return "deep yellow skin";
                case "Skin_Orange":
                    return "orange skin";
                case "Skin_Green":
                    return "green skin";
                default:
                    // Пытаемся определить по названию
                    if (geneDefName.Contains("Green") || geneDefName.Contains("зел"))
                        return "green skin";
                    if (geneDefName.Contains("Blue") || geneDefName.Contains("син"))
                        return "blue skin";
                    if (geneDefName.Contains("Red") || geneDefName.Contains("красн"))
                        return "red skin";
                    if (geneDefName.Contains("Yellow") || geneDefName.Contains("жёлт"))
                        return "yellow skin";
                    if (geneDefName.Contains("Purple") || geneDefName.Contains("фиолет"))
                        return "purple skin";
                    if (geneDefName.Contains("Orange") || geneDefName.Contains("оранж"))
                        return "orange skin";
                    if (geneDefName.Contains("Black") || geneDefName.Contains("чёрн"))
                        return "black skin";
                    if (geneDefName.Contains("White") || geneDefName.Contains("бел"))
                        return "white skin";
                    if (
                        geneDefName.Contains("Gray")
                        || geneDefName.Contains("Grey")
                        || geneDefName.Contains("сер")
                    )
                        return "gray skin";
                    return null;
            }
        }

        /// <summary>
        /// Получает текстовое описание цвета кожи по RGB цвету (fallback метод)
        /// </summary>
        public static string GetSkinToneDescription(Color color)
        {
            // Вычисляем яркость
            float brightness = (color.r + color.g + color.b) / 3f;

            // Определяем оттенок кожи
            if (brightness >= 0.85f)
                return "very fair skin";
            else if (brightness >= 0.75f)
                return "fair skin";
            else if (brightness >= 0.65f)
                return "light skin";
            else if (brightness >= 0.55f)
                return "medium skin";
            else if (brightness >= 0.45f)
                return "olive skin";
            else if (brightness >= 0.35f)
                return "tan skin";
            else if (brightness >= 0.25f)
                return "brown skin";
            else if (brightness >= 0.15f)
                return "dark brown skin";
            else
                return "very dark skin";
        }

        /// <summary>
        /// Получает описание цвета одежды
        /// </summary>
        public static string GetApparelColorDescription(Color color)
        {
            float h,
                s,
                v;
            Color.RGBToHSV(color, out h, out s, out v);

            // Проверяем на оттенки серого
            if (s < 0.1f)
            {
                return GetGrayscaleDescription(v);
            }

            // Определяем оттенок
            string hueDescription = GetHueDescription(h);

            // Модификаторы насыщенности и яркости
            string saturationModifier = "";
            if (s < 0.3f)
                saturationModifier = "pale ";
            else if (s > 0.8f)
                saturationModifier = "vivid ";

            string brightnessModifier = "";
            if (v < 0.3f)
                brightnessModifier = "dark ";
            else if (v > 0.8f)
                brightnessModifier = "bright ";

            return $"{brightnessModifier}{saturationModifier}{hueDescription}".Trim();
        }

        private static string GetGrayscaleDescription(float value)
        {
            if (value >= 0.95f)
                return "white";
            else if (value >= 0.8f)
                return "light gray";
            else if (value >= 0.6f)
                return "gray";
            else if (value >= 0.4f)
                return "dark gray";
            else if (value >= 0.2f)
                return "charcoal";
            else
                return "black";
        }

        private static string GetHueDescription(float hue)
        {
            // Hue from 0 to 1
            if (hue < 0.05f || hue >= 0.95f)
                return "red";
            if (hue < 0.083f)
                return "orange-red";
            if (hue < 0.15f)
                return "orange";
            if (hue < 0.19f)
                return "golden";
            if (hue < 0.22f)
                return "yellow";
            if (hue < 0.35f)
                return "yellow-green";
            if (hue < 0.45f)
                return "green";
            if (hue < 0.52f)
                return "cyan";
            if (hue < 0.58f)
                return "light blue";
            if (hue < 0.65f)
                return "blue";
            if (hue < 0.72f)
                return "deep blue";
            if (hue < 0.78f)
                return "purple";
            if (hue < 0.85f)
                return "violet";
            if (hue < 0.92f)
                return "magenta";

            return "pink";
        }

        private static string GetBrightnessModifier(float value, float saturation)
        {
            // Для волос используем специальные термины
            if (value < 0.2f)
                return "jet black ";
            else if (value < 0.3f)
                return "black ";
            else if (value < 0.45f)
                return "dark ";
            else if (value > 0.85f && saturation < 0.3f)
                return "platinum ";
            else if (value > 0.75f)
                return "light ";
            else
                return "";
        }
    }
}
