using System.Collections.Generic;
using System.Text.RegularExpressions;
using gay.lilyy.Common;
using gay.lilyy.MenuStyling;
using nadena.dev.ndmf;
using nadena.dev.ndmf.vrchat;
using UnityEngine;
using VRC.SDK3.Avatars.ScriptableObjects;
using static VRC.SDK3.Avatars.ScriptableObjects.VRCExpressionsMenu;

[assembly: ExportsPlugin(typeof(MenuStylingPlugin))]

namespace gay.lilyy.MenuStyling
{
    public class MenuStylingPlugin : Plugin<MenuStylingPlugin>
    {
        public override string DisplayName => "MenuStyling";
        public override string QualifiedName => "gay.lilyy.MenuStyling";
        protected override void Configure()
        {
            InPhase(BuildPhase.Optimizing).AfterPlugin("gay.lilyy.MenuIconRemover").Run("SetMenuStyling", ctx =>
            {
                var obj = ComponentHelper.GetComponentInChildrenWithError<MenuStylingConfig>(ctx.AvatarRootObject);
                if (obj != null)
                {
                    var descriptor = ctx.VRChatAvatarDescriptor();
                    var processedMenus = new HashSet<VRCExpressionsMenu>();
                    descriptor.expressionsMenu = DuplicateMenu(descriptor.expressionsMenu, processedMenus);
                    var walkProcessedMenus = new HashSet<VRCExpressionsMenu>();
                    WalkMenu(obj, descriptor.expressionsMenu, walkProcessedMenus);
                    Object.DestroyImmediate(obj);
                }
            });
        }

        private VRCExpressionsMenu DuplicateMenu(VRCExpressionsMenu menu, HashSet<VRCExpressionsMenu> processedMenus)
        {
            if (menu == null) return null;

            // Prevent circular references - if we've already processed this menu, return null to break the cycle
            if (processedMenus.Contains(menu))
            {
                return null;
            }
            processedMenus.Add(menu);

            var newMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
            newMenu.controls = new List<Control>();

            foreach (var control in menu.controls)
            {
                var newControl = new Control
                {
                    name = control.name,
                    type = control.type,
                    icon = control.icon,
                    parameter = control.parameter,
                    subMenu = DuplicateMenu(control.subMenu, processedMenus),
                    value = control.value,
                    style = control.style,
                    labels = control.labels,
                    subParameters = control.subParameters
                };
                newMenu.controls.Add(newControl);
            }

            return newMenu;
        }

        private string StripTextMeshProTags(string text)
        {
            if (string.IsNullOrEmpty(text)) return text;

            // Remove all TextMeshPro/rich text tags
            // Pattern matches: <tag>, </tag>, <tag=value>, <tag="value">, <tag='value'>
            text = Regex.Replace(text, @"<[^>]+>", "");

            return text;
        }

        private void WalkMenu(MenuStylingConfig config, VRCExpressionsMenu menu, HashSet<VRCExpressionsMenu> processedMenus)
        {
            if (menu == null) return;

            // Prevent circular references
            if (processedMenus.Contains(menu))
            {
                return;
            }
            processedMenus.Add(menu);

            foreach (var child in menu.controls)
            {
                if (child.name != " " && child.name != "" && child.name != null) {
                    // Strip all TextMeshPro styling tags first if enabled
                    if (config.RemovePreexistingStyling)
                    {
                        child.name = StripTextMeshProTags(child.name);
                    }
                    
                    if (!child.name.StartsWith(config.Prefix))
                    {
                        child.name = config.Prefix + child.name;
                    }
                    if (!child.name.EndsWith(config.Suffix))
                    {
                        child.name += config.Suffix;
                    }

                }
                if (child.type == Control.ControlType.SubMenu && child.subMenu != null)
                {
                    WalkMenu(config, child.subMenu, processedMenus);
                }
            }
        }
    }
}
