using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine.UI;
using UnityEngine.EventSystems;

/// <summary>
/// Инструмент создания полного игрока с опциональным инвентарём.
/// Tools > Player Builder
/// </summary>
public class PlayerBuilderTool : EditorWindow
{
    // ── Модель ────────────────────────────────────────────────────────────────
    private GameObject characterModel;
    private Transform  headBone;
    private Transform  handBone;

    // ── Параметры движения ────────────────────────────────────────────────────
    private float walkSpeed   = 5f;
    private float runSpeed    = 9f;
    private float crouchSpeed = 2.5f;
    private float jumpHeight  = 1.5f;
    private float gravity     = -9.81f;

    // ── Коллайдер ─────────────────────────────────────────────────────────────
    private float height  = 1.8f;
    private float radius  = 0.5f;
    private float centerY = 0.9f;

    // ── Камера ────────────────────────────────────────────────────────────────
    private bool  addCamera    = true;
    private float cameraHeight = 1.7f;

    // ── Инвентарь ─────────────────────────────────────────────────────────────
    private bool includeInventory  = true;
    private int  inventorySlots    = 36;
    private int  hotbarSlots       = 9;

    // ── Input Actions ─────────────────────────────────────────────────────────
    private UnityEngine.InputSystem.InputActionAsset inputActions;

    // ── Анимации ──────────────────────────────────────────────────────────────
    private AnimationClip idleClip;
    private AnimationClip walkClip;
    private AnimationClip runClip;
    private AnimationClip jumpClip;
    private AnimationClip crouchIdleClip;
    private AnimationClip crouchWalkClip;

    // ── Scroll ────────────────────────────────────────────────────────────────
    private Vector2 _scroll;

    [MenuItem("Tools/Player Builder")]
    public static void ShowWindow()
    {
        GetWindow<PlayerBuilderTool>("Конструктор Персонажа");
    }

    void OnGUI()
    {
        _scroll = EditorGUILayout.BeginScrollView(_scroll);

        GUILayout.Label("Конструктор Персонажа", EditorStyles.boldLabel);

        // ── Секция модели ─────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Модель", EditorStyles.miniBoldLabel);
        characterModel = (GameObject)EditorGUILayout.ObjectField("Модель персонажа", characterModel, typeof(GameObject), false);
        headBone       = (Transform)EditorGUILayout.ObjectField("Кость головы (Head)", headBone, typeof(Transform), true);
        handBone       = (Transform)EditorGUILayout.ObjectField("Кость руки (RightHand)", handBone, typeof(Transform), true);

        if (characterModel != null && GUILayout.Button("Автопоиск костей Head/Hand"))
            AutoFindBones();

        // ── Движение ──────────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Движение", EditorStyles.miniBoldLabel);
        walkSpeed   = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed);
        runSpeed    = EditorGUILayout.FloatField("Скорость бега", runSpeed);
        crouchSpeed = EditorGUILayout.FloatField("Скорость присядки", crouchSpeed);
        jumpHeight  = EditorGUILayout.FloatField("Высота прыжка", jumpHeight);
        gravity     = EditorGUILayout.FloatField("Гравитация", gravity);

        // ── Коллайдер ─────────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Коллайдер CharacterController", EditorStyles.miniBoldLabel);
        height  = EditorGUILayout.FloatField("Высота", height);
        radius  = EditorGUILayout.FloatField("Радиус", radius);
        centerY = EditorGUILayout.FloatField("Центр Y", centerY);

        // ── Камера ────────────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Камера", EditorStyles.miniBoldLabel);
        addCamera    = EditorGUILayout.Toggle("Добавить камеру", addCamera);
        if (addCamera)
            cameraHeight = EditorGUILayout.Slider("Высота камеры", cameraHeight, 1f, 2f);

        // ── Input Actions ─────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Input System", EditorStyles.miniBoldLabel);
        inputActions = (UnityEngine.InputSystem.InputActionAsset)EditorGUILayout.ObjectField(
            "PlayerControls.inputactions",
            inputActions,
            typeof(UnityEngine.InputSystem.InputActionAsset),
            false);
        if (inputActions == null)
            EditorGUILayout.HelpBox("Назначьте Assets/Input/PlayerControls.inputactions", MessageType.Warning);

        // ── Инвентарь ─────────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Инвентарь", EditorStyles.miniBoldLabel);
        includeInventory = EditorGUILayout.Toggle("Включить инвентарь", includeInventory);
        if (includeInventory)
        {
            inventorySlots = EditorGUILayout.IntField("Слотов инвентаря", inventorySlots);
            hotbarSlots    = EditorGUILayout.IntField("Слотов хотбара", hotbarSlots);
        }

        // ── Анимации ──────────────────────────────────────────────────────────
        GUILayout.Space(6);
        GUILayout.Label("Анимации (опционально)", EditorStyles.miniBoldLabel);
        idleClip      = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false);
        walkClip      = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false);
        runClip       = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false);
        jumpClip      = (AnimationClip)EditorGUILayout.ObjectField("Jump", jumpClip, typeof(AnimationClip), false);
        crouchIdleClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Idle", crouchIdleClip, typeof(AnimationClip), false);
        crouchWalkClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Walk", crouchWalkClip, typeof(AnimationClip), false);

        GUILayout.Space(20);

        // ── Кнопки ────────────────────────────────────────────────────────────
        GUI.color = Color.green;
        if (GUILayout.Button("Создать игрока" + (includeInventory ? " + Инвентарь" : "")))
            BuildPlayer("Player");

        GUI.color = Color.yellow;
        if (GUILayout.Button("Создать тестового игрока (капсула)"))
            BuildTestPlayer();

        GUI.color = Color.cyan;
        if (GUILayout.Button("Сохранить как префаб"))
            SaveAsPrefab();

        GUI.color = Color.white;

        GUILayout.Space(10);
        EditorGUILayout.HelpBox(
            "1. Назначьте модель персонажа (опционально)\n" +
            "2. Укажите кость головы и кость руки\n" +
            "3. Назначьте PlayerControls.inputactions\n" +
            "4. Нажмите 'Создать игрока'",
            MessageType.Info);

        EditorGUILayout.EndScrollView();
    }

    // ── Автопоиск костей ─────────────────────────────────────────────────────

    void AutoFindBones()
    {
        if (characterModel == null) return;
        headBone = FindChildBone(characterModel.transform, "head") ??
                   FindChildBone(characterModel.transform, "Head");
        handBone = FindChildBone(characterModel.transform, "hand_r") ??
                   FindChildBone(characterModel.transform, "RightHand") ??
                   FindChildBone(characterModel.transform, "Hand_R") ??
                   FindChildBone(characterModel.transform, "hand");
        Debug.Log($"[PlayerBuilder] Head: {headBone?.name ?? "не найдена"}, Hand: {handBone?.name ?? "не найдена"}");
    }

    // ── Создание игрока ───────────────────────────────────────────────────────

    GameObject BuildPlayerGO(string playerName)
    {
        var player = new GameObject(playerName);

        // CharacterController
        var cc = player.AddComponent<CharacterController>();
        cc.height = height;
        cc.radius = radius;
        cc.center = new Vector3(0, centerY, 0);

        // Скрипт персонажа
        var character = player.AddComponent<charecter>();
        character.walkSpeed   = walkSpeed;
        character.runSpeed    = runSpeed;
        character.crouchSpeed = crouchSpeed;
        character.jumpHeight  = jumpHeight;
        character.gravity     = gravity;

        // Модель
        Transform resolvedHead = headBone;
        Transform resolvedHand = handBone;

        if (characterModel != null)
        {
            var model = (GameObject)PrefabUtility.InstantiatePrefab(characterModel, player.transform);
            model.transform.localPosition = Vector3.zero;
            model.transform.localRotation = Quaternion.identity;

            if (resolvedHead == null)
                resolvedHead = FindChildBone(model.transform, "head") ?? FindChildBone(model.transform, "Head");
            if (resolvedHand == null)
                resolvedHand = FindChildBone(model.transform, "hand_r") ?? FindChildBone(model.transform, "RightHand");

            var modelAnimator = model.GetComponent<Animator>();
            if (modelAnimator != null && modelAnimator.avatar != null)
            {
                var animator = player.AddComponent<Animator>();
                animator.avatar = modelAnimator.avatar;
            }
        }

        // Кость головы (или создаём точку)
        if (resolvedHead == null)
        {
            var headObj = new GameObject("HeadPoint");
            headObj.transform.SetParent(player.transform);
            headObj.transform.localPosition = new Vector3(0, height - 0.2f, 0);
            resolvedHead = headObj.transform;
        }
        character.head = resolvedHead;

        // Камера
        if (addCamera)
        {
            var camObj = new GameObject("PlayerCamera");
            camObj.transform.SetParent(resolvedHead);
            camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
            var cam = camObj.AddComponent<Camera>();
            cam.tag          = "MainCamera";
            cam.nearClipPlane = 0.05f;

            var oldCam = GameObject.FindWithTag("MainCamera");
            if (oldCam != null && oldCam != camObj)
                DestroyImmediate(oldCam);
        }

        // PlayerInput
        var piGO = new GameObject("PlayerInput");
        var pi   = piGO.AddComponent<PlayerInput>();
        if (inputActions != null) pi.actions = inputActions;

        // HandEquipSystem
        if (resolvedHand != null)
        {
            var handEquip = player.AddComponent<HandEquipSystem>();
            handEquip.handBone = resolvedHand;
        }
        else
        {
            Debug.LogWarning("[PlayerBuilder] Кость руки не найдена — HandEquipSystem не добавлен. Назначьте вручную.");
        }

        player.tag = "Player";
        player.transform.position = new Vector3(0, 2, -5);

        // Инвентарь
        if (includeInventory)
            SetupInventoryForPlayer(player);

        return player;
    }

    void BuildPlayer(string name)
    {
        var player = BuildPlayerGO(name);
        Selection.activeGameObject = player;
        Debug.Log($"[PlayerBuilder] Создан: {name}");
    }

    void BuildTestPlayer()
    {
        var savedModel = characterModel;
        characterModel = null;
        var player = BuildPlayerGO("TestPlayer");
        characterModel = savedModel;

        // Визуальная капсула
        var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
        body.name = "Body";
        body.transform.SetParent(player.transform, false);
        body.transform.localPosition = new Vector3(0, centerY, 0);
        body.transform.localScale    = new Vector3(radius * 2, height / 2f, radius * 2);
        DestroyImmediate(body.GetComponent<Collider>());

        Selection.activeGameObject = player;
        Debug.Log("[PlayerBuilder] Создан тестовый игрок (капсула)");
    }

    void SaveAsPrefab()
    {
        string path = EditorUtility.SaveFilePanelInProject("Сохранить префаб", "Player", "prefab", "Выберите место");
        if (string.IsNullOrEmpty(path)) return;

        var temp   = BuildPlayerGO("PlayerTemp");
        var prefab = PrefabUtility.SaveAsPrefabAsset(temp, path);
        DestroyImmediate(temp);
        Selection.activeObject = prefab;
        Debug.Log($"[PlayerBuilder] Сохранено: {path}");
    }

    // ── Создание инвентаря ────────────────────────────────────────────────────

    void SetupInventoryForPlayer(GameObject player)
    {
        // EventSystem
        if (FindObjectOfType<EventSystem>() == null)
        {
            var esGO = new GameObject("EventSystem");
            esGO.AddComponent<EventSystem>();
            esGO.AddComponent<StandaloneInputModule>();
        }

        // InventoryEvents
        new GameObject("InventoryEvents").AddComponent<InventoryEvents>();

        // InventoryManager
        var imGO = new GameObject("InventoryManager");
        var im   = imGO.AddComponent<InventoryManager>();
        im.inventorySize = inventorySlots;

        // InventoryCanvas — дочерний объект Player
        var canvasGO = new GameObject("InventoryCanvas");
        canvasGO.transform.SetParent(player.transform, false);

        var canvas = canvasGO.AddComponent<Canvas>();
        canvas.renderMode   = RenderMode.ScreenSpaceOverlay;
        canvas.sortingOrder = 100;
        canvasGO.AddComponent<UnityEngine.UI.GraphicRaycaster>();

        var uiBuilder = canvasGO.AddComponent<InventoryUIBuilder>();
        uiBuilder.inventoryRows = inventorySlots / 9;
        uiBuilder.hotbarSlots   = hotbarSlots;

        // Строим UI сразу до запуска игры
        uiBuilder.BuildInventoryUI();

        // Назначаем ссылки в InventoryManager
        im.slots           = uiBuilder.GetInventorySlots();
        im.hotbarSlots     = uiBuilder.GetHotbarSlots();
        im.inventoryPanel  = uiBuilder.inventoryPanelRect != null ? uiBuilder.inventoryPanelRect.gameObject : null;
        im.inventoryCanvas = canvas;

        if (im.inventoryPanel != null)
            im.inventoryPanel.SetActive(false);

        Debug.Log("[PlayerBuilder] Инвентарь создан и назначен.");
    }

    // ── Утилиты ───────────────────────────────────────────────────────────────

    Transform FindChildBone(Transform parent, string boneName)
    {
        if (parent == null) return null;
        if (parent.name.ToLower().Contains(boneName.ToLower())) return parent;
        foreach (Transform child in parent)
        {
            var result = FindChildBone(child, boneName);
            if (result != null) return result;
        }
        return null;
    }
}
