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

namespace OCES.Audio
{
    /// <summary>
    /// 维护当前激活的游戏状态，在状态变化时全量匹配 Path 表，返回应当播放的 ContainerId。
    /// </summary>
    public class MusicStateRouter
    {

        // key: StateGroup enum Type，value: 当前激活的 enum 值
        readonly Dictionary<Type, Enum> m_activeStates = new();
        

        readonly MusicPathConfig m_musicPaths;
        readonly AmbiencePathConfig m_ambiencePaths;

        // 上一次匹配到的 PathId，用于 Transition 表的 FromPathId 查询
        public uint LastMusicPathId { get; private set; }
        public uint LastAmbiencePathId { get; private set; }
        internal IReadOnlyDictionary<Type, Enum> ActiveStates { get { return this.m_activeStates; }}

        public MusicStateRouter(MusicPathConfig musicPaths, AmbiencePathConfig ambiencePaths)
        {
            this.m_musicPaths    = musicPaths;
            this.m_ambiencePaths = ambiencePaths;
        }

        /// <summary>
        /// 更新某个 StateGroup 的当前值，并重新全量匹配两张 Path 表。
        /// </summary>
        public void SetState<TEnum>(TEnum state, out uint musicContainerId, out uint ambienceContainerId)
            where TEnum : Enum
        {
            // Dictionary<Type, Enum> 天然保证同一 StateGroup 只保留最新值，直接覆盖即可
            this.m_activeStates[typeof(TEnum)] = state;

            musicContainerId   = MatchBestPath(this.m_musicPaths.MusicPathList(),   out uint musicPathId);
            ambienceContainerId = MatchBestPath(this.m_ambiencePaths.AmbiencePathList(), out uint ambiencePathId);

            LastMusicPathId    = musicPathId;
            LastAmbiencePathId = ambiencePathId;

#if UNITY_EDITOR
            Editor.DebugInfoCollector.Instance.ActiveStates = this.m_activeStates;
#endif
        }

        // ─────────────────────────────────────────────
        // 内部匹配逻辑
        // ─────────────────────────────────────────────

        /// <summary>
        /// 遍历路径列表，找到所有满足当前状态的规则，返回 priority 最小（最高优先级）的那条的 ContainerId。
        /// </summary>
        uint MatchBestPath<T>(List<T> paths, out uint matchedPathId) where T : IPathEntry
        {
            IPathEntry best = null;
            foreach (T path in paths)
            {
                if (PathMatches(path.Path) && (best == null || path.Priority < best.Priority))
                    best = path;
            }

            if (best != null)
            {
                matchedPathId = best.Id;
                return best.ContainerId;
            }

            matchedPathId = 0;
            return 0;
        }

        /// <summary>
        /// 解析 path 字符串，判断当前激活状态是否满足该条规则。
        /// 格式：TypeID1,子状态|TypeID2,子状态……
        /// 规则中的每一个条件都必须满足（AND 关系）。
        /// </summary>
        bool PathMatches(string pathStr)
        {
            if (string.IsNullOrEmpty(pathStr))
                return true; // 空 path 视为无条件匹配（默认兜底规则）

            string[] conditions = pathStr.Split('|');
            foreach (string condition in conditions)
            {
                string[] parts = condition.Split(',');
                if (parts.Length != 2)
                {
                    Debug.LogWarning($"[MusicStateRouter] Path格式错误: '{condition}'");
                    return false;
                }

                if (!int.TryParse(parts[0].Trim(), out int typeId) ||
                    !int.TryParse(parts[1].Trim(), out int stateValue))
                {
                    Debug.LogWarning($"[MusicStateRouter] Path解析失败: '{condition}'");
                    return false;
                }

                bool conditionMet = false;
                foreach (KeyValuePair<Type, Enum> kv in this.m_activeStates)
                {
                    if (StateGroupRegistry.GetTypeId(kv.Key) != typeId || Convert.ToInt32(kv.Value) != stateValue)
                        continue;
                    conditionMet = true;
                    break;
                }

                if (!conditionMet)
                    return false;
            }

            return true;
        }
    }

    // ─────────────────────────────────────────────
    // StateGroup 注册表：将 enum Type 映射为策划表中填写的 TypeId 整数
    // ─────────────────────────────────────────────

    /// <summary>
    /// 程序员在此注册所有 StateGroup enum 与其对应 TypeId 的映射关系。
    /// 策划在 MusicPath.path 字段中填写的 TypeId 数字必须与此处一致。
    /// </summary>
    public static class StateGroupRegistry
    {
        static readonly Dictionary<Type, int> s_typeIdMap = new();

        public static void Register<TEnum>(int typeId) where TEnum : Enum
        {
            s_typeIdMap[typeof(TEnum)] = typeId;
        }

        public static int GetTypeId(Type enumType)
        {
            if (s_typeIdMap.TryGetValue(enumType, out int id))
                return id;
            Debug.LogWarning($"[StateGroupRegistry] 未注册的StateGroup类型: {enumType.Name}，请调用StateGroupRegistry.Register<T>()");
            return -1;
        }
    }
}