using System;
using System.Collections.Generic;
using System.Linq;
using AlicizaX.UI.Extension;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEditorInternal;
using UnityEditor.UI;
using UnityEngine;
using UnityEngine.UI;
using AnimatorControllerParameterType = UnityEngine.AnimatorControllerParameterType;

[CanEditMultipleObjects]
[CustomEditor(typeof(UXButton), true)]
internal class UXButtonEditor : UXSelectableEditor
{
    private enum TabType
    {
        Image,
        Sound,
        Event
    }

    private SerializedProperty m_Mode;
    private SerializedProperty m_OnValueChanged;
    private SerializedProperty m_OnClick;
    private SerializedProperty m_UXGroup;
    private SerializedProperty m_ChildTransitions;

    private ReorderableList m_ChildTransitionList;

    private static Color darkZebraEven = new Color(0.22f, 0.22f, 0.22f);
    private static Color darkZebraOdd = new Color(0.27f, 0.27f, 0.27f);

    private SerializedProperty hoverAudioClip;
    private SerializedProperty clickAudioClip;

    private UXButton mTarget;

    protected override void OnEnable()
    {
        base.OnEnable();
        mTarget = (UXButton)target;

        m_UXGroup = serializedObject.FindProperty("m_UXGroup");
        m_Mode = serializedObject.FindProperty("m_Mode");
        m_OnValueChanged = serializedObject.FindProperty("m_OnValueChanged");
        m_OnClick = serializedObject.FindProperty("m_OnClick");
        m_ChildTransitions = serializedObject.FindProperty("m_ChildTransitions");
        hoverAudioClip = serializedObject.FindProperty("hoverAudioClip");
        clickAudioClip = serializedObject.FindProperty("clickAudioClip");

        CreateChildTransitionList();

        // 不再 Register Image（基类已经创建），改为 Append 到 base 的 Image 页签
        AppendToTab("Image", DrawImageHead, false);
        AppendToTab("Image", DrawImageBottom);

        // 另外注册独立的 Sound / Event 页签
        RegisterTab("Sound", "d_AudioSource Icon", DrawSoundTab);
        RegisterTab("Event", "EventTrigger Icon", DrawEventTab);
    }

    protected override void OnDisable()
    {
        // 移除之前追加到 Image 页签的回调，避免残留
        RemoveCallbackFromTab("Image", DrawImageHead);
        UnregisterTab("Sound");
        UnregisterTab("Event");

        base.OnDisable();
    }

    private void CreateChildTransitionList()
    {
        m_ChildTransitionList = new ReorderableList(serializedObject, m_ChildTransitions, true, false, true, true);

        m_ChildTransitionList.drawElementBackgroundCallback = (rect, index, isActive, isFocused) =>
        {
            var background = index % 2 == 0 ? darkZebraEven : darkZebraOdd;
            EditorGUI.DrawRect(rect, background);
        };

        m_ChildTransitionList.drawElementCallback = (rect, index, isActive, isFocused) =>
        {
            var element = m_ChildTransitionList.serializedProperty.GetArrayElementAtIndex(index);
            rect.y += 2;

            string elementTitle = $"Null Transition";
            var targetProp = element.FindPropertyRelative("targetGraphic");
            if (targetProp.objectReferenceValue != null)
                elementTitle = targetProp.objectReferenceValue.name;

            EditorGUI.LabelField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight),
                elementTitle, EditorStyles.boldLabel);

            rect.y += EditorGUIUtility.singleLineHeight + 2;
            DrawTransitionData(new Rect(rect.x, rect.y, rect.width, 0), element, true);
        };

        m_ChildTransitionList.elementHeightCallback = (index) =>
        {
            return EditorGUIUtility.singleLineHeight +
                   CalculateTransitionDataHeight(m_ChildTransitionList.serializedProperty.GetArrayElementAtIndex(index)) +
                   10;
        };

        m_ChildTransitionList.onAddCallback = (list) =>
        {
            list.serializedProperty.arraySize++;
            serializedObject.ApplyModifiedProperties();
        };

        m_ChildTransitionList.onRemoveCallback = (list) => { ReorderableList.defaultBehaviours.DoRemoveButton(list); };
    }


    // 追加到 base Image 页签的内容
    private void DrawImageHead()
    {
        EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying);
        var modeType = (ButtonModeType)EditorGUILayout.EnumPopup("Mode", (ButtonModeType)m_Mode.enumValueIndex);
        if (modeType != (ButtonModeType)m_Mode.enumValueIndex)
        {
            if (modeType == ButtonModeType.Normal)
            {
                ResetEventProperty(m_OnValueChanged);
                m_UXGroup.objectReferenceValue = null;
            }
            else
            {
                ResetEventProperty(m_OnClick);
            }

            m_Mode.enumValueIndex = (int)modeType;
        }

        EditorGUI.EndDisabledGroup();



    }

    private  void DrawImageBottom()
    {
        GUILayout.Space(5);

        DrawChildTransitions();

        GUILayout.Space(1);
        DrawBasicSettings();
    }

    private void DrawSoundTab()
    {
        GUILayoutHelper.DrawProperty(hoverAudioClip, customSkin, "Hover Sound", "Play", () =>
        {
            if (hoverAudioClip.objectReferenceValue != null)
            {
                PlayAudio((AudioClip)hoverAudioClip.objectReferenceValue);
            }
        });
        GUILayoutHelper.DrawProperty(clickAudioClip, customSkin, "Click Sound", "Play", () =>
        {
            if (clickAudioClip.objectReferenceValue != null)
            {
                PlayAudio((AudioClip)clickAudioClip.objectReferenceValue);
            }
        });
    }

    protected virtual void DrawEventTab()
    {
        if (m_Mode.enumValueIndex == (int)ButtonModeType.Toggle)
        {
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(m_OnValueChanged);
        }
        else
        {
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(m_OnClick);
        }

        EditorGUILayout.Separator();
    }

    // helpers kept from original file
    private void ResetEventProperty(SerializedProperty property)
    {
        SerializedProperty persistentCalls = property.FindPropertyRelative("m_PersistentCalls");
        SerializedProperty calls = persistentCalls.FindPropertyRelative("m_Calls");
        calls.arraySize = 0;
        property.serializedObject.ApplyModifiedProperties();
    }

    private void PlayAudio(AudioClip clip)
    {
        if (clip != null)
        {
            ExtensionHelper.PreviewAudioClip(clip);
        }
    }

    private void DrawBasicSettings()
    {
        if (m_Mode.enumValueIndex == (int)ButtonModeType.Toggle)
        {
            GUILayoutHelper.DrawProperty<UXGroup>(m_UXGroup, customSkin, "UXGroup", (oldValue, newValue) =>
            {
                UXButton self = target as UXButton;
                if (oldValue != null)
                {
                    oldValue.UnregisterButton(self);
                }

                if (newValue != null)
                {
                    newValue.RegisterButton(self);
                }
            });
        }
    }

    private void DrawChildTransitions()
    {
        m_ChildTransitionList.DoLayoutList();
    }

    // CalculateTransitionDataHeight & DrawTransitionData remain the same as earlier to preserve child-only Animation restriction and warnings.
    private float CalculateTransitionDataHeight(SerializedProperty transitionData)
    {
        float height = 0;
        SerializedProperty transition = transitionData.FindPropertyRelative("transition");
        var currentTransition = GetTransition(transition);

        bool isChild = m_ChildTransitions != null &&
                       !string.IsNullOrEmpty(m_ChildTransitions.propertyPath) &&
                       transitionData.propertyPath.StartsWith(m_ChildTransitions.propertyPath);

        if (isChild && currentTransition == Selectable.Transition.Animation)
        {
            currentTransition = Selectable.Transition.ColorTint;
        }

        height += EditorGUIUtility.singleLineHeight * 1.5f;
        height += EditorGUIUtility.singleLineHeight;

        SerializedProperty targetGraphic = transitionData.FindPropertyRelative("targetGraphic");
        var graphic = targetGraphic.objectReferenceValue as Graphic;
        var animator = graphic != null ? graphic.GetComponent<Animator>() : null;

        switch (currentTransition)
        {
            case Selectable.Transition.ColorTint:
                if (graphic == null) height += EditorGUIUtility.singleLineHeight;
                break;
            case Selectable.Transition.SpriteSwap:
                if (!(graphic is Image)) height += EditorGUIUtility.singleLineHeight;
                break;
            case Selectable.Transition.Animation:
                if (animator == null) height += EditorGUIUtility.singleLineHeight;
                break;
        }

        switch (currentTransition)
        {
            case Selectable.Transition.ColorTint:
                height += EditorGUI.GetPropertyHeight(transitionData.FindPropertyRelative("colors"));
                break;
            case Selectable.Transition.SpriteSwap:
                height += EditorGUI.GetPropertyHeight(transitionData.FindPropertyRelative("spriteState"));
                break;
            case Selectable.Transition.Animation:
                height += EditorGUI.GetPropertyHeight(transitionData.FindPropertyRelative("animationTriggers"));
                break;
        }

        return height;
    }

    private void DrawTransitionData(Rect position, SerializedProperty transitionData, bool isChild = false)
    {
        SerializedProperty targetGraphic = transitionData.FindPropertyRelative("targetGraphic");
        SerializedProperty transition = transitionData.FindPropertyRelative("transition");
        SerializedProperty colorBlock = transitionData.FindPropertyRelative("colors");
        SerializedProperty spriteState = transitionData.FindPropertyRelative("spriteState");
        SerializedProperty animationTriggers = transitionData.FindPropertyRelative("animationTriggers");

        EditorGUI.indentLevel++;
        float lineHeight = EditorGUIUtility.singleLineHeight;
        float spacing = 2f;
        float y = position.y;

        var currentTransition = GetTransition(transition);

        if (isChild && currentTransition == Selectable.Transition.Animation)
        {
            Rect warningRect = new Rect(position.x, y, position.width, lineHeight);
            EditorGUI.HelpBox(warningRect, "Animation 过渡仅允许用于 Main Transition，子 Transition 不支持 Animation（已显示为 ColorTint）", MessageType.Warning);
            y += lineHeight + spacing;
            currentTransition = Selectable.Transition.ColorTint;
        }

        switch (currentTransition)
        {
            case Selectable.Transition.ColorTint:
            case Selectable.Transition.SpriteSwap:
                Rect targetRect = new Rect(position.x, y, position.width, lineHeight);
                EditorGUI.PropertyField(targetRect, targetGraphic);
                y += lineHeight + spacing;
                break;
        }

        Rect transitionRect = new Rect(position.x, y, position.width, lineHeight);

        if (isChild)
        {
            string[] options = new[] { "None", "Color Tint", "Sprite Swap" };
            int[] values = new[] { (int)Selectable.Transition.None, (int)Selectable.Transition.ColorTint, (int)Selectable.Transition.SpriteSwap };

            int curVal = transition.enumValueIndex;
            int selIdx = Array.IndexOf(values, curVal);
            if (selIdx < 0) selIdx = 0;

            selIdx = EditorGUI.Popup(transitionRect, "Transition", selIdx, options);
            transition.enumValueIndex = values[selIdx];

            currentTransition = GetTransition(transition);
            y += lineHeight + spacing;
        }
        else
        {
            EditorGUI.PropertyField(transitionRect, transition);
            y += lineHeight + spacing;
        }

        var graphic = targetGraphic.objectReferenceValue as Graphic;
        var animator = graphic != null ? graphic.GetComponent<Animator>() : null;

        switch (currentTransition)
        {
            case Selectable.Transition.ColorTint:
                if (graphic == null)
                {
                    Rect warningRect = new Rect(position.x, y, position.width, lineHeight);
                    EditorGUI.HelpBox(warningRect, "需要Graphic组件来使用颜色过渡", MessageType.Warning);
                    y += lineHeight + spacing;
                }

                break;

            case Selectable.Transition.SpriteSwap:
                if (!(graphic is Image))
                {
                    Rect warningRect = new Rect(position.x, y, position.width, lineHeight);
                    EditorGUI.HelpBox(warningRect, "需要Image组件来使用精灵切换", MessageType.Warning);
                    y += lineHeight + spacing;
                }

                break;
            case Selectable.Transition.Animation:
                if (animator == null)
                {
                    Rect warningRect = new Rect(position.x, y, position.width, lineHeight);
                    EditorGUI.HelpBox(warningRect, "需要Animator组件来使用动画切换", MessageType.Warning);
                    y += lineHeight + spacing;
                }

                break;
        }

        switch (currentTransition)
        {
            case Selectable.Transition.ColorTint:
                CheckAndSetColorDefaults(colorBlock, targetGraphic);
                Rect colorRect = new Rect(position.x, y, position.width, EditorGUI.GetPropertyHeight(colorBlock));
                EditorGUI.PropertyField(colorRect, colorBlock);
                break;

            case Selectable.Transition.SpriteSwap:
                CheckAndSetColorDefaults(colorBlock, targetGraphic);
                Rect spriteRect = new Rect(position.x, y, position.width, EditorGUI.GetPropertyHeight(spriteState));
                EditorGUI.PropertyField(spriteRect, spriteState);
                break;
            case Selectable.Transition.Animation:
                Rect animRect = new Rect(position.x, y, position.width, EditorGUI.GetPropertyHeight(animationTriggers));
                EditorGUI.PropertyField(animRect, animationTriggers);
                break;
        }

        if (graphic != null && currentTransition != (Selectable.Transition)transition.enumValueIndex &&
            ((Selectable.Transition)transition.enumValueIndex == Selectable.Transition.Animation ||
             (Selectable.Transition)transition.enumValueIndex == Selectable.Transition.None))
        {
            graphic.canvasRenderer.SetColor(Color.white);
        }

        EditorGUI.indentLevel--;
    }
}
