using System;
using System.Collections.Generic;
using UnityEngine;

namespace Darkmatter.Libs.UI
{
    /// <summary>
    /// Manages a group of ToggleButton components, ensuring only one can be active at a time.
    /// </summary>
    public class ToggleButtonGroup : MonoBehaviour
    {
        [SerializeField] private List<ToggleButton> toggleButtons = new List<ToggleButton>();
        [SerializeField] private bool allowSwitchOff = false;

        public event Action<ToggleButton> OnToggleSelected;

        public IReadOnlyList<ToggleButton> ToggleButtons => toggleButtons;

        // Cache the delegates to cleanly unsubscribe
        private Dictionary<ToggleButton, Action<bool>> _eventHandlers = new Dictionary<ToggleButton, Action<bool>>();

        private void OnEnable()
        {
            foreach (var button in toggleButtons)
            {
                if (button != null)
                {
                    Action<bool> handler = (isOn) => HandleToggleValueChanged(button, isOn);
                    _eventHandlers[button] = handler;
                    button.OnValueChanged += handler;
                }
            }
        }

        private void OnDisable()
        {
            foreach (var button in toggleButtons)
            {
                if (button != null && _eventHandlers.TryGetValue(button, out var handler))
                {
                    button.OnValueChanged -= handler;
                }
            }
            _eventHandlers.Clear();
        }

        public void AddToggle(ToggleButton toggle)
        {
            if (!toggleButtons.Contains(toggle))
            {
                toggleButtons.Add(toggle);
                if (isActiveAndEnabled)
                {
                    Action<bool> handler = (isOn) => HandleToggleValueChanged(toggle, isOn);
                    _eventHandlers[toggle] = handler;
                    toggle.OnValueChanged += handler;
                }
            }
        }

        public void RemoveToggle(ToggleButton toggle)
        {
            if (toggleButtons.Remove(toggle))
            {
                if (_eventHandlers.TryGetValue(toggle, out var handler))
                {
                    toggle.OnValueChanged -= handler;
                    _eventHandlers.Remove(toggle);
                }
            }
        }

        private void HandleToggleValueChanged(ToggleButton changedButton, bool isOn)
        {
            if (isOn)
            {
                // Turn off all other toggles
                foreach (var button in toggleButtons)
                {
                    if (button != changedButton && button != null)
                    {
                        button.IsOn = false;
                    }
                }
                OnToggleSelected?.Invoke(changedButton);
            }
            else if (!allowSwitchOff)
            {
                // If it was turned off but we don't allow switching off completely,
                // check if any other toggle is on. If not, force this one back on.
                bool anyOn = false;
                foreach (var button in toggleButtons)
                {
                    if (button != null && button.IsOn)
                    {
                        anyOn = true;
                        break;
                    }
                }

                // Actually, due to event ordering, another button might have just turned on.
                // We should only force it on if really no other button is on.
                if (!anyOn)
                {
                    changedButton.IsOn = true;
                }
            }
        }
    }
}
