using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UVC.Log; // 필요에 따라 UVC.Log 또는 프로젝트별 로깅 시스템 사용
using UVC.UI.Menu;

namespace SampleProject.UI.Menu
{
    /// <summary>
    /// <see cref="TopMenuView"/>를 상속받아 특정 프로젝트(이 경우 <c>SampleProject</c>)에 맞게
    /// 상단 메뉴의 시각적 표현과 일부 동작을 커스터마이징하는 View 클래스입니다.
    /// 이 클래스는 프로젝트 고유의 메뉴 아이템 프리팹을 사용하도록 지정하거나,
    /// 메뉴 아이템의 레이아웃, 스타일(예: 비활성화 상태 표시) 등을 프로젝트의 요구사항에 맞게 조정하는 데 사용됩니다.
    /// 주로 <see cref="SampleProjectTopMenuController"/>와 함께 작동하여 메뉴 시스템을 구성합니다.
    /// </summary>
    /// <remarks>
    /// 이 클래스는 <see cref="TopMenuView"/>의 유연성을 활용하여,
    /// 핵심 메뉴 생성 및 관리 로직은 부모 클래스로부터 재사용하면서
    /// UI/UX의 세부적인 부분을 프로젝트 특성에 맞게 차별화할 수 있도록 설계되었습니다.
    /// </remarks>
    /// <example>
    /// 다음은 <c>SampleProjectTopMenuView</c>를 더욱 확장하여,
    /// 게임의 특정 테마나 상태(예: "고대비 모드")에 따라 메뉴의 모양을
    /// 더욱 세밀하게 제어하는 View 클래스를 만드는 가상적인 예제입니다.
    /// <code>
    /// public class ThemedSampleProjectTopMenuView : SampleProjectTopMenuView
    /// {
    ///     // 가상의 현재 애플리케이션 테마 상태 (실제로는 별도의 테마 관리 시스템을 통해 관리될 수 있음)
    ///     private bool useHighContrastTheme = false;
    ///
    ///     // 예시: 현재 테마에 따라 다른 메뉴 아이템 프리팹 경로를 반환하도록 오버라이드
    ///     protected override string MenuItemPrefabPath
    ///     {
    ///         get
    ///         {
    ///             if (useHighContrastTheme)
    ///             {
    ///                 // 고대비 테마용 특별한 메뉴 아이템 프리팹 경로
    ///                 return "Prefabs/UI/Menu/SampleProjectMenuItem_HighContrast";
    ///             }
    ///             // 기본 SampleProject 메뉴 아이템 프리팹 경로 사용 (부모 클래스의 값)
    ///             return base.MenuItemPrefabPath;
    ///         }
    ///     }
    ///
    ///     protected override void Awake()
    ///     {
    ///         base.Awake(); // 부모 클래스(SampleProjectTopMenuView)의 Awake 로직 실행
    ///         ULog.Debug("ThemedSampleProjectTopMenuView Awake: 테마에 맞는 설정 적용 준비됨.");
    ///
    ///         // 여기에 테마별 추가 초기화 로직을 넣을 수 있습니다.
    ///         // 예: 현재 테마 상태(useHighContrastTheme)를 외부 설정이나 이벤트로부터 받아옴
    ///         // useHighContrastTheme = ApplicationThemeManager.IsHighContrastEnabled; // 가상의 테마 관리자
    ///     }
    ///
    ///     // 메뉴 아이템 생성 후, 테마에 맞는 추가 스타일링 적용 예시
    ///     public override Vector2 CreateMenuItems(List&lt;MenuItemData&gt; items, Transform parentContainer, int depth = 0)
    ///     {
    ///         // 부모 클래스(SampleProjectTopMenuView)의 메뉴 생성 로직을 먼저 실행
    ///         Vector2 calculatedSize = base.CreateMenuItems(items, parentContainer, depth);
    ///
    ///         // 생성된 메뉴 아이템들에 대해 테마별 추가 스타일링 적용
    ///         if (useHighContrastTheme)
    ///         {
    ///             foreach (MenuItemData itemData in items)
    ///             {
    ///                 if (itemData.IsSeparator) continue;
    ///
    ///                 if (_menuItemObjects.TryGetValue(itemData.ItemId, out GameObject menuItemInstance))
    ///                 {
    ///                     TextMeshProUGUI buttonText = menuItemInstance.GetComponentInChildren&lt;TextMeshProUGUI&gt;(true);
    ///                     if (buttonText != null)
    ///                     {
    ///                         // 예시: 고대비 테마일 경우 텍스트 색상을 밝은 노란색으로 변경
    ///                         // buttonText.color = Color.yellow;
    ///                     }
    ///                     // Image background = menuItemInstance.GetComponent&lt;Image&gt;();
    ///                     // if (background != null) background.color = Color.black; // 배경을 검게
    ///                 }
    ///             }
    ///             ULog.Debug("ThemedSampleProjectTopMenuView: 고대비 테마 스타일이 적용되었습니다.");
    ///         }
    ///         return calculatedSize;
    ///     }
    ///
    ///     // 외부에서 테마 변경을 알리고 메뉴를 다시 그리도록 하는 메서드 (예시)
    ///     public void ApplyTheme(bool highContrast)
    ///     {
    ///         useHighContrastTheme = highContrast;
    ///         ULog.Debug($"ThemedSampleProjectTopMenuView: 테마 변경됨 (고대비: {useHighContrastTheme}). 메뉴 UI를 업데이트합니다.");
    ///         // 메뉴를 다시 그리려면 Controller를 통해 Model 데이터를 받아와서 ClearMenuItems 후 CreateMenuItems를 다시 호출해야 함.
    ///         // 이 View 클래스 단독으로는 전체 메뉴를 다시 그리는 로직을 직접 트리거하기 어려울 수 있음.
    ///         // 보통 Controller가 이러한 상태 변경을 감지하고 View 업데이트를 지시함.
    ///     }
    /// }
    /// </code>
    /// </example>
    public class SampleProjectTopMenuView : TopMenuView
    {
        /// <summary>
        /// 이 프로젝트(<c>SampleProject</c>)에서 사용할 기본 메뉴 아이템 프리팹의 Resources 폴더 내 경로입니다.
        /// 부모 클래스 <see cref="TopMenuView"/>의 <see cref="TopMenuView.MenuItemPrefabPath"/> 속성을 오버라이드하여
        /// 기본 프리팹 대신 여기에 지정된 프리팹을 사용하도록 합니다.
        /// </summary>
        protected override string MenuItemPrefabPath => "Prefabs/SampleProject/UI/Menu/SampleProjectMenuItem";

        // 주석 처리된 예시 코드:
        // 만약 MenuItemPrefabPath 속성을 오버라이드하는 대신,
        // Awake에서 직접 프리팹을 로드하고 싶다면 아래와 같이 'new' 키워드를 사용하여
        // 부모 클래스와는 별개의 새로운 상수 또는 변수를 선언하고 사용할 수 있습니다.
        // 하지만 속성 오버라이드가 일반적으로 더 깔끔하고 권장되는 방식입니다.
        //
        // /// <summary>
        // /// (덮어쓰기 예시) 프로젝트별 MenuItem 프리팹 경로입니다. 'new'를 사용하여 부모의 변수를 가립니다.
        // /// </summary>
        // private new const string MenuItemPrefabPath = "Prefabs/SampleProject/UI/Menu/SampleMenuItem";
        //
        // /// <summary>
        // /// (덮어쓰기 예시) 프로젝트별 MenuSeparator 프리팹 경로입니다.
        // /// </summary>
        // private new const string MenuSeparatorPrefabPath = "Prefabs/SampleProject/UI/Menu/SampleMenuSeparator";

        /// <summary>
        /// MonoBehaviour의 Awake 메시지입니다. 스크립트 인스턴스가 로드될 때 호출됩니다.
        /// 부모 클래스 <see cref="TopMenuView"/>의 <c>Awake()</c> 로직을 먼저 실행하여
        /// 기본적인 프리팹 로드 및 초기 설정을 수행한 후,
        /// 이 <c>SampleProjectTopMenuView</c>만의 추가적인 초기화 로직을 수행할 수 있습니다.
        /// </summary>
        protected override void Awake()
        {
            // 1. 부모 클래스(TopMenuView)의 Awake() 메서드를 호출합니다.
            //    - 이렇게 하면 TopMenuView에 정의된 기본 프리팹 경로들(MenuItemPrefabPath, SubMenuItemPrefabPath 등)을 사용하여
            //      프리팹들을 로드하고, menuContainer를 찾는 등의 기본 초기화 작업이 수행됩니다.
            //    - 만약 이 클래스(SampleProjectTopMenuView)에서 MenuItemPrefabPath와 같은 속성을 오버라이드했다면,
            //      부모의 Awake()는 오버라이드된 경로를 사용하여 프리팹을 로드합니다.
            base.Awake();

            // 2. 여기에 SampleProjectTopMenuView만의 추가적인 초기화 코드를 작성합니다.
            //    (아래는 주석 처리된 예시들입니다.)

            // 예시 1: 만약 위에서 MenuItemPrefabPath 속성을 오버라이드하지 않고,
            // 'new'로 선언된 별도의 경로 변수(예: private new const string MenuItemPrefabPath)를 사용했다면,
            // 부모가 로드한 menuItemPrefab을 여기서 다시 로드하여 덮어써야 합니다.
            // (하지만 속성 오버라이드가 더 나은 접근 방식입니다.)
            //
            // if (!string.IsNullOrEmpty(MenuItemPrefabPath_SampleProjectSpecific)) // 'new'로 선언된 프로젝트별 경로 변수 사용 가정
            // {
            //     // 부모 클래스(TopMenuView)의 protected 필드인 menuItemPrefab을 직접 덮어씁니다.
            //     menuItemPrefab = Resources.Load<GameObject>(MenuItemPrefabPath_SampleProjectSpecific);
            //     if (menuItemPrefab == null)
            //     {
            //         ULog.Error($"[SampleProject] 메뉴 아이템 프리팹을 Resources 폴더에서 로드할 수 없습니다. 경로: {MenuItemPrefabPath_SampleProjectSpecific}");
            //     }
            // }
            // (menuSeparatorPrefab에 대해서도 유사하게 처리 가능)

            // 예시 2: 프로젝트별로 메뉴 아이템의 기본 크기나 간격 등을 조정하고 싶을 때.
            // 부모 클래스(TopMenuView)에 정의된 protected 필드들을 직접 수정할 수 있습니다.
            // 이 값들은 LayoutMenuItem 등에서 사용됩니다.
            //
            // menuItemSize = new Vector2(120, 35); // 기본 메뉴 아이템 크기를 너비 120, 높이 35로 변경
            // menuItemSpace = new Vector2(5, menuItemSpace.y); // 메뉴 아이템 간 수평 간격을 5로 변경 (수직 간격은 유지)
            // subContainerPadding = new Vector4(8, 8, 8, 8); // 하위 메뉴 컨테이너의 패딩 변경

            ULog.Debug("SampleProjectTopMenuView의 Awake 메서드가 실행 완료되었습니다.");
        }

        /// <summary>
        /// 메뉴 아이템 UI 요소들을 생성하고 배치합니다.
        /// 이 메서드는 부모 클래스 <see cref="TopMenuView"/>의 <see cref="TopMenuView.CreateMenuItems"/>를 오버라이드하여,
        /// 기본적인 메뉴 생성 로직은 부모에게 맡기되, 생성된 후 각 메뉴 아이템의 시각적 표현
        /// (예: <see cref="MenuItemData.IsEnabled"/> 상태에 따른 버튼의 활성화/비활성화 및 스타일)을
        /// 이 프로젝트(<c>SampleProject</c>)의 요구사항에 맞게 추가적으로 커스터마이징합니다.
        /// </summary>
        /// <param name="items">생성할 메뉴 아이템들의 데이터(<see cref="MenuItemData"/>) 리스트입니다.</param>
        /// <param name="parentContainer">생성된 메뉴 아이템들이 자식으로 추가될 부모 Transform입니다.</param>
        /// <param name="depth">현재 생성 중인 메뉴의 깊이입니다 (최상위 메뉴는 0).</param>
        /// <returns>생성된 메뉴 아이템들이 차지하는 전체 영역의 계산된 크기 (너비, 높이)를 반환합니다.</returns>
        public override Vector2 CreateMenuItems(List<MenuItemData> items, Transform parentContainer, int depth = 0)
        {
            // ULog.Debug($"[SampleProject] CreateMenuItems 실행 시작 (Depth: {depth}, 아이템 수: {items?.Count ?? 0})");

            // 1. 부모 클래스(TopMenuView)의 CreateMenuItems 메서드를 호출합니다.
            //    - 이 호출을 통해 기본적인 메뉴 아이템 GameObject들이 프리팹으로부터 생성되고,
            //      텍스트 설정, 기본 이벤트 연결, 하위 메뉴 재귀 생성 등이 수행됩니다.
            //    - 또한, 부모 클래스의 _menuItemObjects 딕셔너리에 생성된 GameObject들이 ItemId를 키로 하여 저장됩니다.
            //    - 반환값은 생성된 메뉴들이 차지하는 계산된 크기입니다.
            Vector2 calculatedSize = base.CreateMenuItems(items, parentContainer, depth);

            // 2. 부모 클래스에서 메뉴 아이템들이 생성된 후, 추가적인 프로젝트별 시각적 처리를 수행합니다.
            //    - _menuItemObjects 딕셔너리는 부모 클래스에 protected로 선언되어 있어 접근 가능합니다.
            //    - 이 딕셔너리를 사용하여 각 MenuItemData에 해당하는 실제 GameObject를 가져올 수 있습니다.
            if (items != null)
            {
                foreach (MenuItemData itemData in items)
                {
                    if (itemData.IsSeparator) continue; // 구분선 아이템은 특별한 시각적 처리가 필요 없을 수 있으므로 건너뜁니다.

                    // _menuItemObjects에서 현재 itemData에 해당하는 GameObject를 찾습니다.
                    if (_menuItemObjects.TryGetValue(itemData.ItemId, out GameObject menuItemInstance))
                    {
                        // GameObject에서 Button 컴포넌트를 가져옵니다.
                        Button button = menuItemInstance.GetComponent<Button>();
                        if (button != null)
                        {
                            // MenuItemData의 IsEnabled 상태에 따라 버튼의 interactable 속성을 설정합니다.
                            // - true이면 버튼이 활성화되어 클릭 가능하게 보입니다.
                            // - false이면 버튼이 비활성화되어 클릭 불가능하게 보입니다.
                            // (실제 클릭 로직 제어는 TopMenuController의 HandleMenuItemClicked에서도 이루어지지만,
                            //  View에서의 시각적인 피드백도 중요합니다.)
                            button.interactable = itemData.IsEnabled;

                            // 추가적으로, 비활성화된 아이템의 텍스트 색상이나 다른 시각적 요소를 변경할 수 있습니다.
                            TextMeshProUGUI buttonText = menuItemInstance.GetComponentInChildren<TextMeshProUGUI>(true); // 비활성화된 자식도 검색
                            if (buttonText != null)
                            {
                                // 예시: 비활성화된 아이템의 텍스트 색상을 약간 어둡게 또는 회색으로 변경
                                // buttonText.color = itemData.IsEnabled ? Color.white : new Color(0.7f, 0.7f, 0.7f, 0.8f);
                                // (실제 사용할 색상 값은 프로젝트의 디자인 가이드에 따라 결정해야 합니다.)
                                // ULog.Debug($"[SampleProject] 아이템 '{itemData.ItemId}'의 버튼 활성 상태: {button.interactable}, 텍스트: {buttonText.text}");
                            }
                        }
                        else
                        {
                            // ULog.Warning($"[SampleProject] 메뉴 아이템 '{itemData.ItemId}'의 GameObject에 Button 컴포넌트가 없습니다.");
                        }
                    }
                    else
                    {
                        // ULog.Warning($"[SampleProject] _menuItemObjects에 ID '{itemData.ItemId}'를 가진 메뉴 아이템 GameObject를 찾을 수 없습니다.");
                    }
                }
            }
            // ULog.Debug($"[SampleProject] CreateMenuItems 실행 완료 (Depth: {depth}). 계산된 크기: {calculatedSize}");
            return calculatedSize; // 부모 클래스가 계산한 크기를 그대로 반환합니다.
        }

        // 필요하다면, 메뉴 아이템의 위치나 크기를 정하는 LayoutMenuItem 등의 다른 메서드도
        // override하여 프로젝트에 특화된 레이아웃 로직을 구현할 수 있습니다.
        //
        // /// <summary>
        // /// (오버라이드 예시) UI 요소(메뉴 아이템 또는 구분선)의 위치와 크기를 설정합니다.
        // /// 부모의 레이아웃 로직을 실행한 후, 프로젝트별 추가적인 시각적 조정을 할 수 있습니다.
        // /// </summary>
        // protected override void LayoutMenuItem(GameObject uiElement, MenuItemData itemData, int depth, int itemIndex, List<MenuItemData> siblingItems)
        // {
        //     // 1. 부모 클래스의 LayoutMenuItem을 호출하여 기본적인 위치 및 크기 설정을 수행합니다.
        //     base.LayoutMenuItem(uiElement, itemData, depth, itemIndex, siblingItems);
        //
        //     // 2. 여기에 프로젝트별 추가적인 레이아웃 조정 로직을 넣습니다.
        //     if (!itemData.IsEnabled && !itemData.IsSeparator)
        //     {
        //         // 예시: 비활성화된 메뉴 아이템의 투명도를 약간 낮추어 시각적으로 덜 강조되게 합니다.
        //         // CanvasGroup canvasGroup = uiElement.GetComponent<CanvasGroup>();
        //         // if (canvasGroup == null) canvasGroup = uiElement.AddComponent<CanvasGroup>();
        //         // canvasGroup.alpha = 0.6f;
        //         // ULog.Debug($"[SampleProject] 비활성화된 아이템 '{itemData.ItemId}'의 투명도 조정됨.");
        //     }
        // }

        // 이 외에도, 프로젝트별로 특정 UI 요소의 동작을 변경하거나 추가적인 시각적 효과를 주고 싶을 때
        // TopMenuView의 다른 virtual 메서드들을 오버라이드하여 구현할 수 있습니다.
        // 예를 들어, 하위 메뉴가 열리거나 닫힐 때 특별한 애니메이션을 추가하거나(ToggleSubMenuDisplay 오버라이드),
        // 메뉴 아이템의 모양을 프로젝트 테마에 맞게 동적으로 변경하는 등의 작업이 가능합니다.
    }
}