using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor.Animations;

public class AnimatorParameterDetailAnalyzer : EditorWindow
{
    private AnimatorController selectedController;
    private Dictionary<string, ParameterUsageData> parameterUsageData = new Dictionary<string, ParameterUsageData>();
    private Vector2 scrollPosition;
    private string analysisResult = "";
    private bool showRawData = false;
    private string targetLayerName = "";

    [MenuItem("Tools/Animator Parameter Detail Analyzer")]
    public static void ShowWindow()
    {
        GetWindow<AnimatorParameterDetailAnalyzer>("Animator Parameter Detail Analyzer");
    }

    private void OnGUI()
    {
        GUILayout.Label("Animator Parameter Detail Analyzer", EditorStyles.boldLabel);

        EditorGUI.BeginChangeCheck();
        selectedController = (AnimatorController)EditorGUILayout.ObjectField("Animator Controller", selectedController, typeof(AnimatorController), false);
        if (EditorGUI.EndChangeCheck())
        {
            AnalyzeController();
        }

        targetLayerName = EditorGUILayout.TextField("Target Layer Name (Empty for all)", targetLayerName);

        if (GUILayout.Button("Analyze Selected Controller"))
        {
            AnalyzeController();
        }

        showRawData = EditorGUILayout.Toggle("Show Raw Data", showRawData);

        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
        EditorGUILayout.TextArea(analysisResult, GUILayout.ExpandHeight(true));
        EditorGUILayout.EndScrollView();
    }

    private void AnalyzeController()
    {
        parameterUsageData.Clear();
        analysisResult = "";

        if (selectedController == null)
        {
            Debug.LogWarning("No Animator Controller selected.");
            return;
        }

        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"=== Animator Controller Analysis: {selectedController.name} ===");
        
        if (string.IsNullOrEmpty(targetLayerName))
        {
            sb.AppendLine("Analyzing ALL layers");
        }
        else
        {
            sb.AppendLine($"Analyzing layer: {targetLayerName}");
        }
        sb.AppendLine();

        foreach (var param in selectedController.parameters)
        {
            parameterUsageData[param.name] = new ParameterUsageData(param);
        }

        foreach (var layer in selectedController.layers)
        {
            if (string.IsNullOrEmpty(targetLayerName) || layer.name == targetLayerName)
            {
                AnalyzeStateMachine(layer.stateMachine, layer.name);
            }
        }

        foreach (var paramData in parameterUsageData.Values.OrderBy(d => d.parameter.name))
        {
            AppendParameterReport(sb, paramData);
        }

        if (showRawData)
        {
            sb.AppendLine();
            sb.AppendLine("=== Raw Transition Data ===");
            foreach (var layer in selectedController.layers)
            {
                if (string.IsNullOrEmpty(targetLayerName) || layer.name == targetLayerName)
                {
                    AppendRawTransitionData(sb, layer.stateMachine, layer.name);
                }
            }
        }

        analysisResult = sb.ToString();
    }

    private void AppendParameterReport(StringBuilder sb, ParameterUsageData paramData)
    {
        var param = paramData.parameter;
        sb.AppendLine($"Parameter: {param.name} ({param.type})");

        sb.Append("  Possible Values: ");
        switch (param.type)
        {
            case AnimatorControllerParameterType.Int:
                sb.AppendLine(string.Join(", ", paramData.possibleIntValues.OrderBy(v => v).Select(v => v.ToString())));
                break;
            case AnimatorControllerParameterType.Float:
                sb.AppendLine(string.Join(", ", paramData.possibleFloatValues.OrderBy(v => v).Select(v => v.ToString("F2"))));
                break;
            case AnimatorControllerParameterType.Bool:
                sb.AppendLine(string.Join(", ", paramData.possibleBoolValues.Select(v => v.ToString())));
                break;
            case AnimatorControllerParameterType.Trigger:
                sb.AppendLine("Trigger (used in conditions)");
                break;
        }

        if (paramData.transitionUsages.Count > 0)
        {
            sb.AppendLine("  Used in Transitions:");
            foreach (var usage in paramData.transitionUsages)
            {
                sb.AppendLine($"    {usage.fromState} -> {usage.toState} (Layer: {usage.layerName})");
                sb.AppendLine($"      Condition: {param.name} {GetConditionSymbol(usage.condition.mode)} {usage.condition.threshold}");
            }
        }
        else
        {
            sb.AppendLine("  Not used in any transitions (may be used in scripts)");
        }

        sb.AppendLine();
    }

    private string GetConditionSymbol(AnimatorConditionMode mode)
    {
        switch (mode)
        {
            case AnimatorConditionMode.If: return "==";
            case AnimatorConditionMode.IfNot: return "!=";
            case AnimatorConditionMode.Greater: return ">";
            case AnimatorConditionMode.Less: return "<";
            case AnimatorConditionMode.Equals: return "==";
            case AnimatorConditionMode.NotEqual: return "!=";
            default: return "?";
        }
    }

    private void AnalyzeStateMachine(AnimatorStateMachine stateMachine, string layerName)
    {
        foreach (var childState in stateMachine.states)
        {
            AnalyzeState(childState.state, layerName);
        }

        foreach (var childStateMachine in stateMachine.stateMachines)
        {
            AnalyzeStateMachine(childStateMachine.stateMachine, layerName);
        }
    }

    private void AnalyzeState(AnimatorState state, string layerName)
    {
        foreach (var transition in state.transitions)
        {
            AnalyzeTransition(transition, state.name, layerName);
        }
    }

    private void AnalyzeTransition(AnimatorStateTransition transition, string fromStateName, string layerName)
    {
        foreach (var condition in transition.conditions)
        {
            if (!parameterUsageData.ContainsKey(condition.parameter))
                continue;

            var paramData = parameterUsageData[condition.parameter];
            var usage = new TransitionUsage
            {
                layerName = layerName,
                fromState = fromStateName,
                toState = transition.destinationState?.name ?? "Exit",
                condition = condition
            };

            paramData.transitionUsages.Add(usage);

            switch (paramData.parameter.type)
            {
                case AnimatorControllerParameterType.Int:
                    paramData.possibleIntValues.Add((int)condition.threshold);
                    break;
                case AnimatorControllerParameterType.Float:
                    paramData.possibleFloatValues.Add(condition.threshold);
                    break;
                case AnimatorControllerParameterType.Bool:
                    paramData.possibleBoolValues.Add(condition.threshold > 0.5f);
                    break;
            }
        }
    }

    private void AppendRawTransitionData(StringBuilder sb, AnimatorStateMachine stateMachine, string layerName)
    {
        foreach (var childState in stateMachine.states)
        {
            foreach (var transition in childState.state.transitions)
            {
                sb.AppendLine($"{layerName}: {childState.state.name} -> {transition.destinationState?.name ?? "Exit"}");
                foreach (var condition in transition.conditions)
                {
                    sb.AppendLine($"  {condition.parameter} {condition.mode} {condition.threshold}");
                }
            }
        }

        foreach (var childStateMachine in stateMachine.stateMachines)
        {
            AppendRawTransitionData(sb, childStateMachine.stateMachine, layerName);
        }
    }

    private class ParameterUsageData
    {
        public AnimatorControllerParameter parameter;
        public HashSet<int> possibleIntValues = new HashSet<int>();
        public HashSet<float> possibleFloatValues = new HashSet<float>();
        public HashSet<bool> possibleBoolValues = new HashSet<bool>();
        public List<TransitionUsage> transitionUsages = new List<TransitionUsage>();

        public ParameterUsageData(AnimatorControllerParameter param)
        {
            parameter = param;
            
            switch (param.type)
            {
                case AnimatorControllerParameterType.Int:
                    possibleIntValues.Add(param.defaultInt);
                    break;
                case AnimatorControllerParameterType.Float:
                    possibleFloatValues.Add(param.defaultFloat);
                    break;
                case AnimatorControllerParameterType.Bool:
                    possibleBoolValues.Add(param.defaultBool);
                    break;
            }
        }
    }

    private class TransitionUsage
    {
        public string layerName;
        public string fromState;
        public string toState;
        public AnimatorCondition condition;
    }
}