using UnityEngine;
using UnityEngine.UI;
using UVC.UI.Toolbar.Model;
using UVC.UI.ToolBar.View;

namespace UVC.UI.Toolbar.View
{
    /// <summary>
    /// <see cref="ToolbarToggleButton"/> 모델의 UI 표현을 생성하고 관리하는 클래스입니다.
    /// 이 클래스는 <see cref="IButtonViewProcessor"/> 인터페이스를 구현하여,
    /// 토글 버튼의 UI GameObject 생성, 이벤트 바인딩, 시각적 업데이트 로직을 담당합니다.
    /// </summary>
    /// <remarks>
    /// 주요 역할:
    /// - <see cref="ToolbarView.toggleButtonPrefab"/>을 사용하여 토글 버튼 UI GameObject를 인스턴스화합니다.
    /// - 생성된 UI의 <see cref="Toggle"/> 컴포넌트와 <see cref="ToolbarToggleButton"/> 모델 간의 상호작용을 설정합니다.
    ///   (예: UI 토글 시 모델의 <see cref="ToolbarToggleButton.ExecuteClick"/> 호출)
    /// - 모델의 상태 변경(<see cref="ToolbarButtonBase.OnStateChanged"/>, <see cref="ToolbarToggleButton.OnToggleStateChanged"/>)에 따라
    ///   UI의 시각적 요소(텍스트, 아이콘, 토글 상태 등)를 업데이트합니다.
    /// </remarks>
    /// <example>
    /// <code>
    /// // ToolbarView 내에서 이 프로세서가 사용되는 방식 (간략화된 예시):
    /// // ToolbarView view = GetComponent<ToolbarView>();
    /// // ToolbarToggleButton toggleModel = new ToolbarToggleButton { Text = "ToggleMe", IsSelected = true };
    /// //
    /// // IButtonViewProcessor processor = new ToolbarToggleButtonViewProcessor();
    /// //
    /// // // 1. UI 생성
    /// // GameObject buttonUI = processor.CreateButtonUI(toggleModel, view.toolbarContainer, view);
    /// //
    /// // // 2. 상호작용 및 초기 상태 설정
    /// // processor.SetupButtonInteractions(toggleModel, buttonUI, view);
    /// //
    /// // // 3. 모델 상태 변경 시 UI 업데이트 (ToolbarView의 RenderToolbar 내에서 이벤트 구독을 통해 자동 처리됨)
    /// // // toggleModel.IsSelected = false; // 이 변경이 UI에 반영됨
    /// // // toggleModel.Text = "New Text"; // 이 변경도 UI에 반영됨
    /// </code>
    /// </example>
    public class ToolbarToggleButtonViewProcessor : IButtonViewProcessor
    {
        /// <summary>
        /// <see cref="ToolbarToggleButton"/> 모델에 대한 UI GameObject를 생성합니다.
        /// <see cref="ToolbarView.toggleButtonPrefab"/>을 사용하여 인스턴스화합니다.
        /// </summary>
        /// <param name="buttonModel">UI를 생성할 대상인 <see cref="ToolbarButtonBase"/> 타입의 모델 객체입니다. 내부적으로 <see cref="ToolbarToggleButton"/>으로 캐스팅하여 사용합니다.</param>
        /// <param name="parentContainer">생성된 UI GameObject가 자식으로 추가될 부모 <see cref="Transform"/>입니다.</param>
        /// <param name="viewContext">현재 <see cref="ToolbarView"/>의 컨텍스트입니다. 프리팹 참조 등에 사용됩니다.</param>
        /// <returns>생성된 UI GameObject입니다. <see cref="ToolbarView.toggleButtonPrefab"/>이 할당되지 않은 경우 null을 반환할 수 있습니다.</returns>
        public GameObject CreateButtonUI(ToolbarButtonBase buttonModel, Transform parentContainer, ToolbarView viewContext)
        {
            if (viewContext.toggleButtonPrefab == null)
            {
                Debug.LogError("ToggleButtonViewProcessor: toggleButtonPrefab이 ToolbarView에 할당되지 않았습니다.", viewContext);
                return null;
            }
            // toggleButtonPrefab을 사용하여 새 GameObject를 만들고 parentContainer의 자식으로 배치합니다.
            return Object.Instantiate(viewContext.toggleButtonPrefab, parentContainer);
        }

        /// <summary>
        /// 생성된 토글 버튼 UI GameObject에 초기 시각적 요소를 설정하고, 사용자 상호작용 및 모델 상태 변경에 따른 UI 업데이트 로직을 바인딩합니다.
        /// </summary>
        /// <param name="buttonModel">설정할 버튼의 데이터 모델 (<see cref="ToolbarToggleButton"/> 타입이어야 함).</param>
        /// <param name="buttonUIObject">모델에 해당하는, 화면에 표시될 UI GameObject.</param>
        /// <param name="viewContext">현재 <see cref="ToolbarView"/>의 컨텍스트.</param>
        /// <remarks>
        /// 이 메서드는 다음을 수행합니다:
        /// 1. <paramref name="buttonModel"/>을 <see cref="ToolbarToggleButton"/>으로 캐스팅합니다.
        /// 2. <paramref name="buttonUIObject"/>에서 <see cref="Toggle"/> 컴포넌트를 찾습니다.
        /// 3. <see cref="Toggle"/> 컴포넌트의 초기 `isOn` 상태를 모델의 <see cref="ToolbarToggleButton.IsSelected"/> 값으로 설정합니다. (UI 이벤트 발생 없이)
        /// 4. <see cref="Toggle"/> 컴포넌트의 `onValueChanged` 이벤트에 리스너를 추가하여, UI에서 토글 상태가 변경되면 모델의 <see cref="ToolbarToggleButton.ExecuteClick"/> 메서드를 호출합니다.
        ///    이를 통해 모델의 상태가 업데이트되고, 연결된 커맨드가 실행될 수 있습니다.
        /// 5. <see cref="UpdateCommonButtonVisuals"/>를 호출하여 텍스트, 아이콘 등 공통 시각 요소를 초기화합니다.
        /// 6. <see cref="UpdateToggleStateVisuals"/>를 호출하여 토글 상태에 따른 시각적 표현(예: 아이콘 변경)을 초기화합니다.
        /// </remarks>
        public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
        {
            ToolbarToggleButton toggleModel = buttonModel as ToolbarToggleButton;
            if (toggleModel == null) return;

            Toggle toggleComponent = buttonUIObject.GetComponent<Toggle>();
            if (toggleComponent != null)
            {
                // 1. 모델의 현재 선택 상태로 UI의 Toggle 컴포넌트 상태를 초기화합니다.
                //    SetIsOnWithoutNotify를 사용하여 이 변경으로 인해 onValueChanged 이벤트가 발생하지 않도록 합니다.
                toggleComponent.SetIsOnWithoutNotify(toggleModel.IsSelected);

                // 2. UI의 Toggle 컴포넌트의 값이 변경될 때(사용자가 클릭 등) 모델의 ExecuteClick 메서드를 호출합니다.
                //    ExecuteClick 내부에서 IsSelected 상태가 변경되고, 관련 커맨드가 실행되며, OnToggleStateChanged 이벤트가 발생합니다.
                toggleComponent.onValueChanged.AddListener((isSelected) =>
                {
                    // isSelected 파라미터는 UI에서 변경된 새 상태이지만,
                    // ToolbarToggleButton의 ExecuteClick() 내부에서 IsSelected가 토글되므로
                    // isSelected 파라미터를 직접 사용하지 않고 ExecuteClick()만 호출합니다.
                    // ExecuteClick()이 모델의 상태를 올바르게 변경하고 이벤트를 발생시킬 책임이 있습니다.
                    toggleModel.ExecuteClick();
                });
            }
            else
            {
                Debug.LogError($"ToggleButtonViewProcessor: ToggleButton '{toggleModel.Text}'의 GameObject에 Toggle 컴포넌트가 없습니다.", buttonUIObject);
            }

            // 공통 시각적 요소(텍스트, 아이콘, 활성화 상태) 업데이트
            UpdateCommonButtonVisuals(buttonModel, buttonUIObject, viewContext);

            // 토글 상태에 따른 시각적 요소(예: 선택/해제 시 아이콘 변경) 업데이트
            // 이 호출은 초기 상태를 반영하고, 모델의 IsSelected 값에 따라 올바른 아이콘(On/Off)을 표시하도록 합니다.
            UpdateToggleStateVisuals(toggleModel, buttonUIObject, toggleModel.IsSelected, viewContext);
        }

        /// <summary>
        /// 버튼 모델의 공통적인 상태(텍스트, 아이콘, 활성화 상태 등)가 변경되었을 때,
        /// 해당 버튼 UI의 시각적 요소를 업데이트합니다.
        /// 이 메서드는 <see cref="ToolbarView.InternalUpdateCommonButtonVisuals"/>를 호출하여 실제 업데이트 로직을 수행합니다.
        /// </summary>
        /// <param name="buttonModel">상태가 변경된 버튼의 모델입니다.</param>
        /// <param name="buttonUIObject">업데이트할 UI GameObject입니다.</param>
        /// <param name="viewContext">현재 <see cref="ToolbarView"/>의 컨텍스트입니다.</param>
        public void UpdateCommonButtonVisuals(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
        {
            // ToolbarView에 있는 공통 업데이트 로직을 사용합니다.
            // 이 메서드는 텍스트, 기본 아이콘(토글 상태에 따라 다를 수 있음), 활성화 상태(interactable) 등을 업데이트합니다.
            viewContext.InternalUpdateCommonButtonVisuals(buttonModel, buttonUIObject);
        }

        /// <summary>
        /// <see cref="ToolbarToggleButton"/>의 선택 상태(<see cref="ToolbarToggleButton.IsSelected"/>)가 모델에서 변경되었을 때 호출됩니다.
        /// 해당 UI <see cref="Toggle"/> 컴포넌트의 `isOn` 상태를 모델의 <see cref="ToolbarToggleButton.IsSelected"/> 값과 동기화하고,
        /// 선택 상태에 따른 아이콘 변경 등을 위해 <see cref="ToolbarView.InternalUpdateCommonButtonVisuals"/>를 호출합니다.
        /// </summary>
        /// <param name="toggleButtonModel">IsSelected 상태가 변경된 토글 버튼의 모델입니다.</param>
        /// <param name="buttonUIObject">업데이트할 UI GameObject입니다.</param>
        /// <param name="isSelected">모델의 새로운 <see cref="ToolbarToggleButton.IsSelected"/> 값입니다.</param>
        /// <param name="viewContext">현재 <see cref="ToolbarView"/>의 컨텍스트입니다.</param>
        /// <remarks>
        /// 이 메서드는 주로 모델의 <see cref="ToolbarToggleButton.OnToggleStateChanged"/> 이벤트에 의해 호출됩니다.
        /// UI의 <see cref="Toggle"/> 컴포넌트 상태를 모델과 동기화하고,
        /// 선택/해제 상태에 따라 다른 아이콘을 사용한다면 <see cref="ToolbarView.InternalUpdateCommonButtonVisuals"/>가 이를 처리합니다.
        /// </remarks>
        public void UpdateToggleStateVisuals(ToolbarToggleButton toggleButtonModel, GameObject buttonUIObject, bool isSelected, ToolbarView viewContext)
        {
            Toggle toggleComponent = buttonUIObject.GetComponent<Toggle>();
            if (toggleComponent != null)
            {
                // 모델의 IsSelected 상태와 UI의 Toggle.isOn 상태가 다를 경우에만 UI를 업데이트합니다.
                // 이는 불필요한 UI 업데이트 및 이벤트 발생을 방지합니다.
                if (toggleComponent.isOn != isSelected)
                {
                    toggleComponent.SetIsOnWithoutNotify(isSelected);
                }
            }

            // 아이콘 업데이트를 위해 InternalUpdateCommonButtonVisuals를 다시 호출합니다.
            // ToolbarToggleButton은 IsSelected 상태에 따라 다른 아이콘(IconSpritePath 또는 OffIconSpritePath)을
            // 가질 수 있으므로, 이 상태 변경 시 아이콘도 업데이트되어야 합니다.
            // InternalUpdateCommonButtonVisuals 내부에서 ToolbarToggleButton 타입인지 확인하고 적절한 아이콘 경로를 사용합니다.
            viewContext.InternalUpdateCommonButtonVisuals(toggleButtonModel, buttonUIObject);
        }
    }
}