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>
        /// Получает текстовое описание цвета кожи, сначала проверяя гены, затем используя цвет как fallback
        /// </summary>
        public static string GetSkinToneDescription(Pawn pawn)
        {
            // Сначала проверяем гены цвета кожи
            string geneSkinTone = GetSkinToneFromGenes(pawn);
            if (!string.IsNullOrEmpty(geneSkinTone))
            {
                return geneSkinTone;
            }

            // Fallback к определению по цвету
            return GetSkinToneDescription(pawn.story.SkinColor);
        }

        /// <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 GetSkinToneFromGenes(Pawn pawn)
        {
            if (pawn?.genes?.GenesListForReading == null)
                return null;

            // Ищем активные гены цвета кожи
            var skinColorGenes = pawn
                .genes.GenesListForReading.Where(gene =>
                    gene.Active && IsSkinColorGene(gene.def.defName)
                )
                .ToList();

            if (!skinColorGenes.Any())
                return null;

            // Берем первый найденный ген (обычно у персонажа один ген цвета кожи)
            var skinGene = skinColorGenes[0];
            return GetSkinToneDescriptionFromGene(skinGene.def.defName);
        }

        /// <summary>
        /// Проверяет, является ли ген геном цвета кожи
        /// </summary>
        private static bool IsSkinColorGene(string geneDefName)
        {
            return geneDefName.StartsWith("Skin_")
                || geneDefName.Contains("SkinColor")
                || geneDefName.Contains("SkinTone");
        }

        /// <summary>
        /// Получает описание цвета кожи по названию гена
        /// </summary>
        private static string GetSkinToneDescriptionFromGene(string geneDefName)
        {
            // Проверяем стандартные гены
            string standardGene = GetStandardGeneSkinTone(geneDefName);
            if (!string.IsNullOrEmpty(standardGene))
                return standardGene;

            // Проверяем дополнительные гены
            string additionalGene = GetAdditionalGeneSkinTone(geneDefName);
            if (!string.IsNullOrEmpty(additionalGene))
                return additionalGene;

            // Пытаемся извлечь информацию из названия
            return ExtractSkinToneFromGeneName(geneDefName);
        }

        /// <summary>
        /// Получает описание для стандартных генов цвета кожи
        /// </summary>
        private static string GetStandardGeneSkinTone(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:
                    return null;
            }
        }

        /// <summary>
        /// Получает описание для дополнительных генов цвета кожи
        /// </summary>
        private static string GetAdditionalGeneSkinTone(string geneDefName)
        {
            switch (geneDefName)
            {
                case "Skin_Dark":
                    return "dark skin";
                case "Skin_Light":
                    return "light skin";
                case "Skin_Medium":
                    return "medium skin";
                case "Skin_Fair":
                    return "fair skin";
                case "Skin_Tan":
                    return "tan skin";
                case "Skin_Olive":
                    return "olive skin";
                case "Skin_Brown":
                    return "brown skin";
                default:
                    return null;
            }
        }

        /// <summary>
        /// Извлекает описание цвета кожи из названия гена
        /// </summary>
        private static string ExtractSkinToneFromGeneName(string geneDefName)
        {
            if (geneDefName.Contains("Black"))
                return "black skin";
            if (geneDefName.Contains("White"))
                return "white skin";
            if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey"))
                return "gray skin";
            if (geneDefName.Contains("Blue"))
                return "blue skin";
            if (geneDefName.Contains("Red"))
                return "red skin";
            if (geneDefName.Contains("Green"))
                return "green skin";
            if (geneDefName.Contains("Yellow"))
                return "yellow skin";
            if (geneDefName.Contains("Purple"))
                return "purple skin";
            if (geneDefName.Contains("Orange"))
                return "orange skin";

            return null; // Неизвестный ген
        }

        /// <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 "";
        }
    }
}
