// Assets/_Project/Scripts/Editor/Gameplay/WaveGoldEntryDrawer.cs
using UnityEditor;
using UnityEngine;
using TD.Gameplay;

namespace TD.Editor.Gameplay
{
    /// <summary>
    /// Custom property drawer for <see cref="WaveGoldEntry"/>. Renders the standard fields
    /// followed by a read-only "Preview Total" line computed from the entry's values, so
    /// designers can see at a glance how much a single player could earn from a wave.
    /// </summary>
    /// <remarks>
    /// The preview includes the kill-reward portion only when the entry's <c>Wave</c>
    /// reference is assigned (it's needed to count enemies in that wave). When unset, the
    /// preview shows just <c>CompletionBonus + NoLeaksBonus</c> and labels itself so the
    /// designer knows to drop a WaveDefinition in for a complete number.
    /// </remarks>
    [CustomPropertyDrawer(typeof(WaveGoldEntry))]
    public class WaveGoldEntryDrawer : PropertyDrawer
    {
        private const float PreviewLineExtraHeight = 4f;

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            // Sum the children + one extra line for the preview label. We render children
            // ourselves rather than using EditorGUI.PropertyField default since we want a
            // foldout with our custom preview tacked onto the end.
            if (!property.isExpanded) return EditorGUIUtility.singleLineHeight;

            float h = EditorGUIUtility.singleLineHeight; // foldout
            h += SpacedLineHeight() * 4;                  // Wave + GoldPerEnemy + Completion + NoLeaks
            h += SpacedLineHeight() + PreviewLineExtraHeight; // preview label
            return h;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            // Foldout header.
            Rect headerRect = new Rect(position.x, position.y, position.width,
                                       EditorGUIUtility.singleLineHeight);
            property.isExpanded = EditorGUI.Foldout(headerRect, property.isExpanded, label,
                                                   toggleOnLabelClick: true);
            if (!property.isExpanded) return;

            float y = position.y + SpacedLineHeight();
            float indent = 14f;
            Rect Row()
            {
                Rect r = new Rect(position.x + indent, y, position.width - indent,
                                  EditorGUIUtility.singleLineHeight);
                y += SpacedLineHeight();
                return r;
            }

            // Standard property fields.
            var waveProp        = property.FindPropertyRelative("Wave");
            var perEnemyProp    = property.FindPropertyRelative("GoldPerEnemy");
            var completionProp  = property.FindPropertyRelative("CompletionBonus");
            var noLeaksProp     = property.FindPropertyRelative("NoLeaksBonus");

            EditorGUI.PropertyField(Row(), waveProp);
            EditorGUI.PropertyField(Row(), perEnemyProp);
            EditorGUI.PropertyField(Row(), completionProp);
            EditorGUI.PropertyField(Row(), noLeaksProp);

            // Compute the preview total. We instantiate the same logic as the runtime
            // property — read the serialized values, count enemies in the optional Wave,
            // sum it all up. Done inline (rather than calling WaveGoldEntry.PreviewTotalGold
            // directly) because SerializedProperty edits aren't applied to the target object
            // until ApplyModifiedProperties runs at the end of the frame, so reading the
            // backing class instance here would show stale data while the user is typing.
            int perEnemy   = perEnemyProp.intValue;
            int completion = completionProp.intValue;
            int noLeaks    = noLeaksProp.intValue;
            var waveAsset  = waveProp.objectReferenceValue as WaveDefinition;

            int enemyCount = 0;
            if (waveAsset != null && waveAsset.Entries != null)
            {
                foreach (var e in waveAsset.Entries)
                {
                    if (e.EnemyType != null && e.Count > 0)
                        enemyCount += e.Count;
                }
            }

            int total = perEnemy * enemyCount + completion + noLeaks;

            // Preview line. Slightly dimmed style, italic, non-editable. Includes a
            // breakdown so the designer can see where the number came from.
            y += PreviewLineExtraHeight;
            Rect previewRect = new Rect(position.x + indent, y, position.width - indent,
                                         EditorGUIUtility.singleLineHeight);

            string breakdown = waveAsset != null
                ? $"Preview Total: {total} g   ({perEnemy} × {enemyCount} enemies " +
                  $"+ {completion} completion + {noLeaks} no-leak)"
                : $"Preview Total: {completion + noLeaks} g   (bonuses only — assign Wave " +
                  $"to include kill rewards)";

            var prevStyle = new GUIStyle(EditorStyles.miniLabel) { fontStyle = FontStyle.Italic };
            using (new EditorGUI.DisabledScope(true))
            {
                EditorGUI.LabelField(previewRect, breakdown, prevStyle);
            }
        }

        private static float SpacedLineHeight()
            => EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
    }
}
