using System;
using System.Collections.Generic;
using System.Linq;
using RootMotion.FinalIK;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace NBF
{
    public class RF4FixPrefab : Editor
    {
        #region 圈

        [MenuItem("Assets/Fix/修复圈", false, 1)]
        private static void FixRings()
        {
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixRing(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼圈失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixRing(GameObject prefab)
        {
            var rings = prefab.GetComponent<RodRingAsset>();
            if (rings == null)
            {
                rings = prefab.AddComponent<RodRingAsset>();
            }

            List<Transform> list = new List<Transform>();
            // 遍历所有直接子对象
            for (int i = 0; i < prefab.transform.childCount; i++)
            {
                Transform child = prefab.transform.GetChild(i);
                list.Add(child);
            }

            // rings.rings = list.ToArray();

            List<Transform> points = new List<Transform>();
            foreach (var tran in list)
            {
                for (int i = 0; i < tran.childCount; i++)
                {
                    Transform c = tran.GetChild(i);
                    if (c.name.Contains("Collider"))
                    {
                        points.Add(c);
                        break;
                    }
                }
            }

            // rings.points = points.ToArray();

            List<RodRingNode> saveList = new List<RodRingNode>();

            foreach (var node in list)
            {
                RodRingNode ringNode = new RodRingNode
                {
                    ring = node
                };
                foreach (var point in points)
                {
                    if (point.parent != node) continue;
                    ringNode.point = point;
                    var rig = point.GetComponent<Rigidbody>();
                    if (rig == null)
                    {
                        rig = point.gameObject.AddComponent<Rigidbody>();
                    }

                    if (rig != null)
                    {
                        rig.useGravity = false;
                        rig.isKinematic = true;
                        rig.mass = 1;
                    }

                    break;
                }

                saveList.Add(ringNode);
            }

            rings.rings = saveList.ToArray();
            EditorUtility.SetDirty(prefab);
        }

        #endregion

        #region 鱼竿

        //joint_root
        [MenuItem("Assets/Fix/修复鱼竿", false, 2)]
        private static void FixRods()
        {
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixRod(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼竿失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixRod(GameObject prefab)
        {
            RemoveMissingScriptsFrom(prefab);


            var lineRenderer = prefab.GetComponent<LineRenderer>();
            if (lineRenderer == null)
            {
                lineRenderer = prefab.AddComponent<LineRenderer>();
            }

            lineRenderer.startWidth = 0.001f;
            lineRenderer.endWidth = 0.001f;

            var rod = prefab.GetComponent<RodAsset>();
            if (rod == null)
            {
                rod = prefab.AddComponent<RodAsset>();
            }

            rod.lineRenderer = lineRenderer;
            rod.root = FindTransformsByNameContainsOnes(prefab.transform, "joint_root");
            rod.LeftHandConnector = FindTransformsByNameContainsOnes(prefab.transform, "l_hand_connector");
            rod.RightHandConnector = FindTransformsByNameContainsOnes(prefab.transform, "r_hand_connector");
            rod.ReelConnector = FindTransformsByNameContainsOnes(prefab.transform, "reel_connector");
            rod.gripEnd = FindTransformsByNameContainsOnes(prefab.transform, "grip_end");

            var trans = prefab.GetComponentsInChildren<Transform>(true);

            List<Transform> joints = new List<Transform>();
            List<Transform> rings = new List<Transform>();
            foreach (var tran in trans)
            {
                if (tran == null) continue;
                if (tran == rod.root) continue;
                if (tran.name.Contains("_RING_"))
                {
                    rings.Add(tran);
                }
                else if (tran.name.Contains("_joint_"))
                {
                    joints.Add(tran);
                }
            }

            var blancEnd = FindTransformByName(prefab.transform, "blanc_end");
            if (blancEnd == null)
            {
                Debug.LogError($"blanc_end 为空，name={prefab.name}");
            }
            else
            {
                joints.Add(blancEnd);
            }

            rod.rings = rings.ToArray();
            rod.joints = joints.ToArray();


            var ccdIK = prefab.GetComponent<CCDIK>();
            if (ccdIK == null)
            {
                ccdIK = prefab.AddComponent<CCDIK>();
            }

            var solver = ccdIK.solver;
            if (solver != null)
            {
                solver.maxIterations = 3;


                var rootField = solver.GetType().GetField("root",
                    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                if (rootField != null)
                {
                    rootField.SetValue(solver, prefab.transform);
                }

                solver.bones = Array.Empty<IKSolver.Bone>();
                for (var i = 1; i < rod.joints.Length; i++)
                {
                    solver.AddBone(rod.joints[i]);
                }
            }

            EditorUtility.SetDirty(rod);
            EditorUtility.SetDirty(ccdIK);
            EditorUtility.SetDirty(prefab);
        }

        #endregion

        #region 线轴

        private static List<AnimationClip> _animationClips;

        [MenuItem("Assets/Fix/修复线轴", false, 3)]
        private static void FixReels()
        {
            _animationClips = GetAllClips();
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixReel(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复线轴失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixReel(GameObject prefab)
        {
            RemoveMissingScriptsFrom(prefab);
            var reel = prefab.GetComponent<ReelAsset>();
            if (reel == null)
            {
                reel = prefab.AddComponent<ReelAsset>();
            }

            reel.rootConnector = FindTransformsByNameContainsOnes(prefab.transform, "reel_root_connector");
            reel.rootCompensator = FindTransformsByNameContainsOnes(prefab.transform, "reel_root_compensator");
            reel.lineConnector = FindTransformsByNameContainsOnes(prefab.transform, "line_connector");
            reel.lineIntersect = FindTransformsByNameContainsOnes(prefab.transform, "line_intersect");
            reel.lineIntersectHelper = reel.lineIntersect.parent;
            reel.handle = FindTransformsByNameContainsOnes(prefab.transform, "ik_locator_handle");
            reel.handleEnd = reel.handle.parent;


            var anim = reel.rootConnector.parent.GetComponent<Animator>();
            if (anim == null)
            {
                anim = reel.rootConnector.parent.gameObject.AddComponent<Animator>();
            }

            reel.animator = anim;

            // var anim = reel.rootConnector.parent.GetComponent<Animation>();
            // if (anim == null)
            // {
            //     anim = reel.rootConnector.parent.gameObject.AddComponent<Animation>();
            // }

            // List<AnimationClip> clips = _animationClips.Where(clip => clip.name.Contains(prefab.name)).ToList();
            // foreach (var clip in clips)
            // {
            //     anim.AddClip(clip, clip.name);
            //     var lowName = clip.name.ToLower();
            //     if (lowName.Contains("open"))
            //     {
            //         reel.openAnimation = clip;
            //     }
            //     else if (lowName.Contains("close"))
            //     {
            //         reel.closeAnimation = clip;
            //     }
            //     else if (lowName.Contains("handle_roll"))
            //     {
            //         reel.rollHandleAnimation = clip;
            //     }
            // }


            // anim.playAutomatically = true;
            // reel.anim = anim;
        }

        #endregion

        #region 浮漂

        [MenuItem("Assets/Fix/修复浮漂", false, 4)]
        private static void FixBobbers()
        {
            _animationClips = GetAllClips();
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixBobber(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼漂失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixBobber(GameObject prefab)
        {
            // RemoveMissingScriptsFrom(prefab);
            var bobber = prefab.GetComponent<BobberAsset>();
            if (bobber == null)
            {
                bobber = prefab.AddComponent<BobberAsset>();
            }

            bobber.body = FindTransformsByNameContainsOnes(prefab.transform, "_body");
            bobber.stick = FindTransformsByNameContainsOnes(prefab.transform, "_stick");
            bobber.topConnector = FindTransformsByNameContainsOnes(prefab.transform, "_topConnector");
            bobber.bottomConnector = FindTransformsByNameContainsOnes(prefab.transform, "_bottomConnector");
            bobber.waterline = FindTransformsByNameContainsOnes(prefab.transform, "_waterline");

            // var boxCollider = prefab.GetComponent<BoxCollider>();
            // if (boxCollider != null)
            // {
            //     DestroyImmediate(boxCollider);
            //     // boxCollider = prefab.AddComponent<BoxCollider>();
            // }
            //
            // boxCollider.center = new Vector3(0, -0.01f, 0);
            // boxCollider.size = new Vector3(0.005f, 0.005f, 0.005f);

            var rigidbody = prefab.GetComponent<Rigidbody>();
            if (rigidbody == null)
            {
                rigidbody = prefab.AddComponent<Rigidbody>();
            }

            rigidbody.useGravity = false;

            var configurableJoint = prefab.GetComponent<ConfigurableJoint>();
            if (configurableJoint == null)
            {
                configurableJoint = prefab.AddComponent<ConfigurableJoint>();
            }

            configurableJoint.xMotion = ConfigurableJointMotion.Locked;
            configurableJoint.yMotion = ConfigurableJointMotion.Locked;
            configurableJoint.zMotion = ConfigurableJointMotion.Locked;
        }

        #endregion

        #region 钩

        [MenuItem("Assets/Fix/修复鱼钩", false, 5)]
        private static void FixHooks()
        {
            _animationClips = GetAllClips();
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixHook(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼钩失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixHook(GameObject prefab)
        {
            // RemoveMissingScriptsFrom(prefab);
            var hook = prefab.GetComponent<HookAsset>();
            if (hook == null)
            {
                hook = prefab.AddComponent<HookAsset>();
            }

            hook.baitConnector = FindTransformsByNameContainsOnes(prefab.transform, "bait_connector");

            var boxCollider = prefab.GetComponent<BoxCollider>();
            if (boxCollider == null)
            {
                boxCollider = prefab.AddComponent<BoxCollider>();
            }

            boxCollider.center = new Vector3(0, -0.01f, 0);
            boxCollider.size = new Vector3(0.005f, 0.005f, 0.005f);

            var rigidbody = prefab.GetComponent<Rigidbody>();
            if (rigidbody == null)
            {
                rigidbody = prefab.AddComponent<Rigidbody>();
            }

            rigidbody.useGravity = false;

            var configurableJoint = prefab.GetComponent<ConfigurableJoint>();
            if (configurableJoint == null)
            {
                configurableJoint = prefab.AddComponent<ConfigurableJoint>();
            }

            configurableJoint.xMotion = ConfigurableJointMotion.Locked;
            configurableJoint.yMotion = ConfigurableJointMotion.Locked;
            configurableJoint.zMotion = ConfigurableJointMotion.Locked;
        }

        #endregion

        #region 鱼饵

        [MenuItem("Assets/Fix/修复鱼饵", false, 6)]
        private static void FixBaits()
        {
            _animationClips = GetAllClips();
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixBait(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼钩失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixBait(GameObject prefab)
        {
            var bait = prefab.GetComponent<BaitAsset>();
            if (bait == null)
            {
                bait = prefab.AddComponent<BaitAsset>();
            }

            bait.hook = FindTransformsByNameContainsOnes(prefab.transform, "_hook");
        }

        #endregion

        #region 仿生饵

        [MenuItem("Assets/Fix/修复路亚饵", false, 6)]
        private static void FixLures()
        {
            _animationClips = GetAllClips();
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixLure(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼钩失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixLure(GameObject prefab)
        {
            RemoveMissingScriptsFrom(prefab);
            var lure = prefab.GetComponent<LureAsset>();
            if (lure == null)
            {
                lure = prefab.AddComponent<LureAsset>();
            }

            List<Transform> hookPoints = new List<Transform>();
            for (int i = 1; i < 5; i++)
            {
                var hook = FindTransformByName(prefab.transform, $"hook_0{i}");
                if (hook == null) break;
                hookPoints.Add(hook);
            }

            lure.hookPoints = hookPoints.ToArray();
            // hook_01
        }

        #endregion

        #region 鱼

        [MenuItem("Assets/Fix/修复鱼", false, 7)]
        private static void FixFishs()
        {
            _animationClips = GetAllClips();
            var rods = GetSelectPrefab<GameObject>();
            foreach (var rod in rods)
            {
                try
                {
                    FixFish(rod);
                    EditorUtility.SetDirty(rod);
                }
                catch (Exception e)
                {
                    Debug.LogError($"修复鱼钩失败，name={rod.name}  e={e}");
                }
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void FixFish(GameObject prefab)
        {
            var bait = prefab.GetComponent<FishAsset>();
            if (bait == null)
            {
                bait = prefab.AddComponent<FishAsset>();
            }
        }

        #endregion

        #region 工具类

        private static List<AnimationClip> GetAllClips()
        {
            List<AnimationClip> list = new List<AnimationClip>();
            // 获取项目中所有的AnimationClip
            string[] guids = AssetDatabase.FindAssets("t:AnimationClip");

            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(path);

                if (clip != null)
                {
                    list.Add(clip);
                }
            }

            return list;
        }

        private static string GetPathToParent(Transform currentTransform)
        {
            if (currentTransform == null || currentTransform.parent == null)
            {
                return string.Empty; // 如果没有父级，返回空字符串
            }

            // 递归调用，先获取父级的路径，然后加上当前Transform的名字
            return GetPathToParent(currentTransform.parent) + "/" + currentTransform.name;
        }

        private static T FindFirstComponentInChildren<T>(GameObject parent) where T : Component
        {
            // 检查当前对象
            T component = parent.GetComponent<T>();
            if (component != null)
            {
                return component;
            }

            // 递归检查子对象
            foreach (Transform child in parent.transform)
            {
                T result = FindFirstComponentInChildren<T>(child.gameObject);
                if (result != null)
                {
                    return result;
                }
            }

            return null;
        }

        private static Transform FindTransformByName(Transform parent, string name)
        {
            // 检查当前对象
            if (parent.name == name)
            {
                return parent;
            }

            // 递归检查子对象
            foreach (Transform child in parent)
            {
                Transform result = FindTransformByName(child, name);
                if (result != null)
                {
                    return result;
                }
            }

            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="namePrefix"></param>
        /// <returns></returns>
        private static List<Transform> FindTransformsByNamePrefix(Transform parent, string namePrefix)
        {
            List<Transform> result = new List<Transform>();

            // 检查当前对象
            if (parent.name.StartsWith(namePrefix))
            {
                result.Add(parent);
            }

            // 递归检查子对象
            foreach (Transform child in parent)
            {
                result.AddRange(FindTransformsByNamePrefix(child, namePrefix));
            }

            return result;
        }

        private static Transform FindTransformsByNameContainsOnes(Transform parent, string nameContains)
        {
            var trans = FindTransformsByNameContains(parent, nameContains);
            if (trans != null && trans.Count > 0)
            {
                return trans.First();
            }

            return null;
        }

        /// <summary>
        /// 获取首个包含制定名字的tran
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="nameContains"></param>
        /// <returns></returns>
        private static List<Transform> FindTransformsByNameContains(Transform parent, string nameContains)
        {
            List<Transform> result = new List<Transform>();

            // 检查当前对象
            if (parent.name.Contains(nameContains))
            {
                result.Add(parent);
            }

            // 递归检查子对象
            foreach (Transform child in parent)
            {
                result.AddRange(FindTransformsByNameContains(child, nameContains));
            }

            return result;
        }

        private static T[] GetSelectPrefab<T>(string ext = ".prefab") where T : Object
        {
            // 获取当前选中的路径
            string selectedPath = GetSelectedFolderPath();

            if (string.IsNullOrEmpty(selectedPath))
            {
                Debug.LogWarning("No folder selected.");
                return Array.Empty<T>();
            }

            List<T> list = new List<T>();
            // 获取该文件夹中的所有资产路径
            string[] assetGuids = AssetDatabase.FindAssets("", new[] { selectedPath });

            foreach (string guid in assetGuids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);

                // 检查路径是否以 ".prefab" 结尾
                if (path.EndsWith(ext))
                {
                    var prefab = AssetDatabase.LoadAssetAtPath<T>(path);
                    if (prefab != null)
                    {
                        list.Add(prefab);
                    }
                }
            }

            return list.ToArray();
        }

        /// <summary>
        /// 移除missing的脚步
        /// </summary>
        /// <param name="objects"></param>
        /// <returns></returns>
        private static int RemoveMissingScriptsFrom(params GameObject[] objects)
        {
            List<GameObject> forceSave = new();
            int removedCounter = 0;
            foreach (GameObject current in objects)
            {
                if (current == null) continue;

                int missingCount = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(current);
                if (missingCount == 0) continue;

                GameObjectUtility.RemoveMonoBehavioursWithMissingScript(current);
                EditorUtility.SetDirty(current);

                if (EditorUtility.IsPersistent(current) && PrefabUtility.IsAnyPrefabInstanceRoot(current))
                    forceSave.Add(current);

                Debug.Log($"Removed {missingCount} Missing Scripts from {current.gameObject.name}", current);
                removedCounter += missingCount;
            }

            foreach (GameObject o in forceSave) PrefabUtility.SavePrefabAsset(o);

            return removedCounter;
        }

        /// <summary>
        /// 获取选中的文件夹路径
        /// </summary>
        /// <returns></returns>
        private static string GetSelectedFolderPath()
        {
            // 获取当前选中的对象
            Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);

            if (selection.Length > 0)
            {
                string path = AssetDatabase.GetAssetPath(selection[0]);

                if (AssetDatabase.IsValidFolder(path))
                {
                    return path;
                }
            }

            return null;
        }

        /// <summary>
        /// 在所有子对象中查找名字为childName的对象
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="childName"></param>
        /// <returns></returns>
        public static Transform FindDeepChild(Transform parent, string childName)
        {
            Transform result = parent.Find(childName);
            if (result != null)
                return result;

            foreach (Transform child in parent)
            {
                result = FindDeepChild(child, childName);
                if (result != null)
                    return result;
            }

            return null;
        }

        #endregion
    }
}