using BepuPhysics.Collidables;
using BepuPhysics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace CtrEditor.Simulacion
{
    public class simBase
    {
        public object WpfObject { get; set; }
        public string SimObjectType { get; set; }
        public BodyHandle BodyHandle { get; protected set; }
        public Simulation _simulation;
        protected bool _bodyCreated = false; // Bandera para saber si hemos creado un cuerpo
        protected SimulationManagerBEPU _simulationManager; // ✅ NUEVO: Referencia al manager

        // ✅ CORREGIDO: Restaurar factor de conversión correcto
        static public float SpeedConversionFactor
        {
            get => 60f; // Factor de conversión de velocidad interna a m/s 
        }

        // Constantes para las posiciones Z de los objetos 3D
        public const float zPos_Transporte = 0f; // Z de la parte baja
        public const float zAltura_Transporte = 0.1f; // Altura del transporte sobre zPos

        public const float zPos_Guia = 0.05f; // Z de la parte baja
        public const float zAltura_Guia = 0.20f; // Altura de la guía sobre zPos
        public const float zPos_Barrera = zPos_Transporte + zAltura_Transporte + 0.05f; // Z de la parte baja - 0.1 Altura Botella
        public const float zPos_Descarte = 0.1f; // Z de la parte baja

        // Constantes para configuración
        public const float zPos_Curve = zPos_Transporte+ zAltura_Transporte; // Z de la parte alta de la curva


        public void RemoverBody()
        {
            try
            {
                // Solo intentar remover si realmente hemos creado un cuerpo antes
                if (_bodyCreated && _simulation != null && _simulation.Bodies != null && _simulation.Bodies.BodyExists(BodyHandle))
                {
                    _simulation.Bodies.Remove(BodyHandle);
                    _bodyCreated = false; // Marcar como no creado después de remover
                    //System.Diagnostics.Debug.WriteLine($"[simBase.RemoverBody] ✅ Body eliminado: {BodyHandle}");
                }
                //else
                //{
                //    System.Diagnostics.Debug.WriteLine($"[simBase.RemoverBody] ⚠️ Body no existe o no creado: {BodyHandle}");
                //}
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[simBase.RemoverBody] ❌ ERROR: {ex.Message}");
                _bodyCreated = false; // Marcar como no creado en caso de error
            }
        }

        /// <summary>
        /// ✅ NUEVO: Cambia la forma de un body existente, limpiando la forma anterior para evitar memory leaks
        /// </summary>
        protected void ChangeBodyShape(TypedIndex newShapeIndex)
        {
            if (_simulation != null && _simulation.Bodies.BodyExists(BodyHandle))
            {
                var bodyReference = _simulation.Bodies.GetBodyReference(BodyHandle);

                // ✅ CRÍTICO: Obtener la forma anterior para limpiarla del pool de shapes
                var oldShapeIndex = bodyReference.Collidable.Shape;

                // Cambiar a la nueva forma
                _simulation.Bodies.SetShape(BodyHandle, newShapeIndex);

                // ✅ CRÍTICO: Limpiar la forma anterior del pool para evitar memory leaks
                // Nota: Solo limpiar si es diferente (para evitar limpiar la forma que acabamos de asignar)
                if (oldShapeIndex.Packed != newShapeIndex.Packed)
                {
                    try
                    {
                        _simulation.Shapes.RemoveAndDispose(oldShapeIndex, _simulation.BufferPool);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"[simBase] Warning: Could not dispose old shape: {ex.Message}");
                        // Continuar - esto no es crítico para la funcionalidad
                    }
                }
            }
        }

        public static float Min(float Value, float Min = 0.01f)
        {
            return Math.Max(Value, Min);
        }

        public static float GradosARadianes(float grados)
        {
            return grados * (float)Math.PI / 180f;
        }

        public static float RadianesAGrados(float radianes)
        {
            return radianes * 180f / (float)Math.PI;
        }

        public void SetPosition(float x, float y, float z = 0)
        {
            CoordinateConverter.UpdateBepuBodyPosition(_simulation, BodyHandle, new Vector3(x, y, z));
        }

        public void SetPosition(Vector2 wpfPosition)
        {
            // Mantener la coordenada Z actual para preservar la altura del objeto
            var currentBepuPosition = CoordinateConverter.GetBepuBodyPosition(_simulation, BodyHandle);
            var newBepuPosition = new Vector3(wpfPosition.X, CoordinateConverter.WpfYToBepuY(wpfPosition.Y), currentBepuPosition.Z);
            CoordinateConverter.UpdateBepuBodyPosition(_simulation, BodyHandle, newBepuPosition);
        }

        public void SetPosition(Vector3 bepuPosition)
        {
            CoordinateConverter.UpdateBepuBodyPosition(_simulation, BodyHandle, bepuPosition);
        }

        public Vector3 GetPosition()
        {
            return CoordinateConverter.GetBepuBodyPosition(_simulation, BodyHandle);
        }

        public void SetRotation(float wpfAngle)
        {
            CoordinateConverter.UpdateBepuBodyRotation(_simulation, BodyHandle, wpfAngle);
        }

        public float GetRotationZ()
        {
            return CoordinateConverter.GetWpfAngleFromBepuBody(_simulation, BodyHandle);
        }
    }

}
