using System;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Intrepid.Core.Themes
{
    [Serializable]
    public class ColorContrast
    {
        [SerializeField, ColorUsage(true, false)] private Color borderOut = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color borderIn = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color background = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color text = new(0,0,0,0);

        public Color BorderOut => borderOut;
        public Color BorderIn => borderIn;
        public Color Background => background;
        public Color Text => text;
    }

    [Serializable]
    public class ColorStates
    {
        [SerializeField, ColorUsage(true, false)] private Color selected = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color available = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color clicked = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color denied = new(0,0,0,0);

        public Color Selected => selected;
        public Color Available => available;
        public Color Clicked => clicked;
        public Color Denied => denied;
    }

    [Serializable]
    public class ColorEmphasis
    {
        [SerializeField, ColorUsage(true, false)] private Color emphasis0 = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color emphasis1 = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color emphasis2 = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color emphasis3 = new(0,0,0,0);
        [SerializeField, ColorUsage(true, false)] private Color emphasis4 = new(0,0,0,0);

        public Color Emphasis0 => emphasis0;
        public Color Emphasis1 => emphasis1;
        public Color Emphasis2 => emphasis2;
        public Color Emphasis3 => emphasis3;
        public Color Emphasis4 => emphasis4;
    }
    
    [Serializable]
    public class ColorInteractable
    {
        [SerializeField, ColorUsage(true, true)] private Color available = new(0,0,0,0);
        [SerializeField, ColorUsage(true, true)] private Color selected = new(0,0,0,0);
        [SerializeField, ColorUsage(true, true)] private Color clicked = new(0,0,0,0);
        [SerializeField, ColorUsage(true, true)] private Color denied = new(0,0,0,0);
        [SerializeField, ColorUsage(true, true)] private Color hijacked = new(0,0,0,0);

        public Color Selected => selected;
        public Color Available => available;
        public Color Clicked => clicked;
        public Color Denied => denied;
        public Color Hijacked => hijacked;
    }
    
    [Serializable]
    public class PaletteBundle
    {
        [Title("Background and Text", bold: false), SerializeField, HideLabel, InlineProperty] private ColorContrast contrast = new();
        [Title("States", bold: false), SerializeField, HideLabel, InlineProperty] private ColorStates states = new();
        [Title("Dynamic", bold: false), SerializeField, HideLabel, InlineProperty] private ColorEmphasis emphasis = new();
        [Title("Interactable", bold: false), SerializeField, HideLabel, InlineProperty] private ColorInteractable interactable = new();

        public ColorContrast Contrast => contrast;
        public ColorStates States => states;
        public ColorEmphasis Emphasis => emphasis;
        public ColorInteractable Interactable => interactable;
        public Color[] Summary => new[]
        {
            Contrast.BorderIn,
            States.Available,
            States.Selected,
            States.Clicked,
            Emphasis.Emphasis4,
        };

        private static void SetValueByReflection(object o, string fieldName, object value)
        {
            Functions.SetValueByReflection(o, fieldName, value);
        }
        
        [Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
        private void StartInteractableFromStates()
        {
            SetValueByReflection(Interactable, "selected", States.Selected);
            SetValueByReflection(Interactable, "available", States.Available);
            SetValueByReflection(Interactable, "clicked", States.Clicked);
            SetValueByReflection(Interactable, "denied", States.Denied);
            SetValueByReflection(Interactable, "hijacked", Emphasis.Emphasis2);
        }

        public bool TryApplyPalette(string input)
        {
            if (string.IsNullOrWhiteSpace(input)) return false;
            var colorStrings = input.Split(',');
            if (colorStrings.Length < 13)
            {
                Debug.LogWarning("Palette string must contain at least 11 hex colors.");
                return false;
            }

            try
            {
                var parsed = new Color[colorStrings.Length];
                for (var i = 0; i < colorStrings.Length; i++)
                {
                    if (ColorUtility.TryParseHtmlString(colorStrings[i].Trim(), out var color))
                        parsed[i] = color;
                    else
                        throw new FormatException($"Invalid color code: {colorStrings[i]}");
                }

                // Map colors by index to target structure
                SetValueByReflection(Contrast, "background", parsed[0]);
                SetValueByReflection(Contrast, "text", parsed[1]);
                SetValueByReflection(Contrast, "borderIn", parsed[2]);
                SetValueByReflection(Contrast, "borderOut", parsed[3]);

                SetValueByReflection(States, "selected", parsed[4]);
                SetValueByReflection(States, "available", parsed[5]);
                SetValueByReflection(States, "clicked", parsed[6]);
                SetValueByReflection(States, "denied", parsed[7]);
                
                for (var i = 0; i < 8; i++)
                {
                    SetValueByReflection(Emphasis, $"emphasis{i}", parsed[8 + i]);
                }

                return true;
            }
            catch (Exception ex)
            {
                Debug.LogError($"Failed to parse palette: {ex.Message}");
                return false;
            }
        }
    }
}