using System.Collections.Generic;
using System.Linq;
using gay.lilyy.Common;
using gay.lilyy.BetterParamMerger;
using nadena.dev.ndmf;
using nadena.dev.ndmf.vrchat;
using UnityEngine;
using VRC.SDK3.Avatars.ScriptableObjects;

[assembly: ExportsPlugin(typeof(BetterParamMergerPlugin))]

namespace gay.lilyy.BetterParamMerger
{
    public class BetterParamMergerPlugin : Plugin<BetterParamMergerPlugin>
    {
        public override string DisplayName => "Better Param Merger";
        public override string QualifiedName => "gay.lilyy.BetterParamMerger";

        protected override void Configure()
        {
            InPhase(BuildPhase.Optimizing).Run("MergeParameters", ctx =>
            {
                var configs = ctx.AvatarRootObject.GetComponentsInChildren<BetterParamMergerConfig>(true);
                if (configs == null || configs.Length == 0)
                    return;

                var descriptor = ctx.VRChatAvatarDescriptor();
                if (descriptor.expressionParameters == null)
                {
                    Debug.LogWarning($"[Better Param Merger] No expression parameters found on avatar {ctx.AvatarRootObject.name}");
                    return;
                }

                // Duplicate the parameters asset to avoid modifying the original
                var originalParams = descriptor.expressionParameters;
                var newParams = ScriptableObject.CreateInstance<VRCExpressionParameters>();
                var paramList = new List<VRCExpressionParameters.Parameter>();
                if (originalParams.parameters != null)
                {
                    paramList.AddRange(originalParams.parameters);
                }
                newParams.parameters = paramList.ToArray();

                // Create a dictionary for quick lookup of existing parameters by name
                var paramDict = paramList.ToDictionary(p => p.name, p => p);

                // Iterate over all config components
                foreach (var config in configs)
                {
                    if (config == null || config.parameterAssets == null)
                        continue;

                    // Iterate over all VRCExpressionParameters assets in this config
                    foreach (var paramAsset in config.parameterAssets)
                    {
                        if (paramAsset == null || paramAsset.parameters == null)
                            continue;

                        // Iterate over all parameters in this asset
                        foreach (var param in paramAsset.parameters)
                        {
                            if (string.IsNullOrEmpty(param.name))
                                continue;

                            if (paramDict.ContainsKey(param.name))
                            {
                                // Parameter exists - update its settings
                                var existingParam = paramDict[param.name];
                                existingParam.valueType = param.valueType;
                                existingParam.defaultValue = param.defaultValue;
                                existingParam.saved = param.saved;
                                existingParam.networkSynced = param.networkSynced;
                            }
                            else
                            {
                                // Parameter doesn't exist - add it
                                var newParam = new VRCExpressionParameters.Parameter
                                {
                                    name = param.name,
                                    valueType = param.valueType,
                                    defaultValue = param.defaultValue,
                                    saved = param.saved,
                                    networkSynced = param.networkSynced
                                };
                                paramList.Add(newParam);
                                paramDict[param.name] = newParam;
                            }
                        }
                    }

                    // Destroy the config component after processing
                    Object.DestroyImmediate(config);
                }

                // Update the parameters array from the list
                newParams.parameters = paramList.ToArray();

                // Assign the new parameters asset to the descriptor
                descriptor.expressionParameters = newParams;
            });
        }
    }
}

