using CtrEditor.FuncionesBase;
using CtrEditor.ObjetosSim;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Color = System.Windows.Media.Color;
using System;

namespace CtrEditor
{
    // Clase para almacenar el estado básico de un objeto para undo
    public class ObjectState
    {
        public int ObjectId { get; set; }
        public float Left { get; set; }
        public float Top { get; set; }
        public float Angle { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }

        public ObjectState(osBase obj)
        {
            ObjectId = obj.Id.Value;
            Left = obj.Left;
            Top = obj.Top;
            Angle = obj.Angulo;
            Width = obj.Ancho;
            Height = obj.Alto;
        }

        public ObjectState(ObjectState other)
        {
            ObjectId = other.ObjectId;
            Left = other.Left;
            Top = other.Top;
            Angle = other.Angle;
            Width = other.Width;
            Height = other.Height;
        }
    }

    // Clase para almacenar un estado completo del workspace
    public class UndoState
    {
        public List<ObjectState> ObjectStates { get; set; }
        public DateTime Timestamp { get; set; }

        public UndoState()
        {
            ObjectStates = new List<ObjectState>();
            Timestamp = DateTime.Now;
        }

        public UndoState(IEnumerable<osBase> objects) : this()
        {
            foreach (var obj in objects)
            {
                ObjectStates.Add(new ObjectState(obj));
            }
        }
    }

    public enum AlignmentType
    {
        Left,
        Right,
        Top,
        Bottom,
        CenterHorizontally,
        CenterVertically,
        DistributeHorizontally,
        DistributeVertically,
        EqualWidth,
        EqualHeight,
        EqualAngle,
        JoinHorizontally,
        JoinVertically
    }

    /// <summary>
    /// Gestor de manipulación de objetos que maneja la selección, movimiento, rotación y redimensionamiento de objetos.
    /// 
    /// MEJORAS PARA OBJETOS ROTADOS:
    /// - HandleResizeForObject: Aplica transformaciones matemáticas para convertir los cambios del mouse
    ///   desde coordenadas del canvas a coordenadas locales del objeto rotado.
    /// - DetermineHandleMode: Adapta el comportamiento de los handles según la rotación del objeto.
    /// - GetAdaptiveCursors: Cambia los cursores de los handles para reflejar la orientación actual del objeto.
    /// 
    /// Estas mejoras hacen que el redimensionamiento sea más intuitivo cuando los objetos están rotados,
    /// ya que los handles responden de acuerdo a la orientación del objeto en lugar de las coordenadas
    /// absolutas del canvas.
    /// </summary>
    public class ObjectManipulationManager
    {
        private enum ResizeMode
        {
            None,
            Move,
            Rotate,
            ResizeWidth,
            ResizeHeight,
            ResizeBoth
        }

        private enum HandleMode
        {
            None,
            Move,
            ResizeWidth,
            ResizeHeight,
            ResizeBoth,
            Rotate
        }

        private ResizeMode _currentResizeMode;
        private readonly MainWindow _mainWindow;
        private readonly Canvas _canvas;
        private Point _lastMousePosition;
        private bool _isDrawingCanvas = false;
        private bool _isDraggingUserControl = false;
        private bool _isMovingUserControl = false;
        private UserControl _currentDraggingControl;
        private Point _startPointUserControl;
        private Point _transformedBoundingBoxCenter;
        private float _lastAngle;
        private List<Rectangle> _resizeRectangles = new List<Rectangle>();
        private List<Rectangle> _highlightRectangles = new List<Rectangle>();
        private System.Threading.Timer _timerRemoveHighlight = null;
        private Rectangle _currentDraggingRectangle;
        private dataDebug _dataDebug = new dataDebug();
        private ObservableCollection<osBase> _selectedObjects = new ObservableCollection<osBase>();
        private List<Rectangle> _selectionHighlightRectangles = new List<Rectangle>();  // Add this line
        private List<(UserControl Control, Rectangle Highlight)> _selectionHighlightPairs = new List<(UserControl, Rectangle)>();
        private Point _rectangleStart;
        public Rectangle _selectionRectangle;  // Cambiado a private
        private ScrollViewer _scrollViewer;  // Add this line
        private Image _backgroundImage;      // Add this line
        internal bool IsDraggingCanvas { get; set; }
        private bool _isRectangleSelectionActive;
        private bool _selectedObjectsAreVisible;

        // Sistema de Undo
        private Stack<UndoState> _undoHistory = new Stack<UndoState>();
        private const int MaxUndoSteps = 3;
        private bool _isApplyingUndo = false;

        public bool IsRectangleSelectionActive
        {
            get => _isRectangleSelectionActive;
            set
            {
                _isRectangleSelectionActive = value;
                if (value)
                {
                    // Al activar la selección por rectángulo, desactivar el panning
                    IsDraggingCanvas = false;
                }
            }
        }

        // Propiedad pública para verificar si hay un rectángulo de selección activo
        public bool HasActiveSelectionRectangle => _selectionRectangle != null;

        public ObjectManipulationManager(MainWindow mainWindow, Canvas canvas)
        {
            _mainWindow = mainWindow;
            _canvas = canvas;
            _scrollViewer = mainWindow.ImagenEnTrabajoScrollViewer;  // Add this line
            _backgroundImage = mainWindow.ImagenDeFondo;             // Add this line
        }

        private void PurgeDeletedObjects()
        {
            var deletedObjects = _selectedObjects.Where(obj =>
                obj.VisualRepresentation == null ||
                !_canvas.Children.Contains(obj.VisualRepresentation)).ToList();

            foreach (var obj in deletedObjects)
            {
                DeselectObject(obj);
            }
        }

        public ObservableCollection<osBase> SelectedObjects
        {
            get
            {
                PurgeDeletedObjects();
                return _selectedObjects;
            }
            private set
            {
                _selectedObjects = value;
                UpdateSelectionVisuals();
            }
        }

        public void UpdateSelectionVisuals()
        {
            PurgeDeletedObjects();
            // Asegurarse de que el canvas haya actualizado su layout
            _canvas.UpdateLayout();

            RemoveResizeRectangles();
            if (_selectedObjects.Any())
            {
                // Verificar si la simulación está activa
                if (_mainWindow.DataContext is MainViewModel viewModel && !viewModel.IsSimulationRunning)
                {
                    AddResizeRectangles(_selectedObjects);
                    UpdateSelectionHighlights();
                }
            }
        }

        public void SuscribirEventos(UserControl userControl)
        {
            userControl.MouseEnter += UserControl_MouseEnter;
            userControl.MouseLeave += UserControl_MouseLeave;
            userControl.Cursor = Cursors.Hand;

            userControl.MouseLeftButtonDown += UserControl_MouseLeftButtonDown;
            userControl.MouseLeftButtonUp += UserControl_MouseLeftButtonUp;
            userControl.MouseMove += UserControl_MouseMove;
        }

        private void UserControl_MouseEnter(object sender, MouseEventArgs e)
        {
            if (sender is UserControl userControl && userControl is IDataContainer dataContainer)
            {
                dataContainer.Highlight(true);

                if (_mainWindow.DataContext is MainViewModel viewModel)
                {
                    var selectedObject = viewModel.SelectedItemOsList;

                    if (selectedObject?.VisualRepresentation != userControl)
                    {
                        AddHighlightRectangles(userControl);
                    }
                }
            }
        }

        private void UserControl_MouseLeave(object sender, MouseEventArgs e)
        {
            if (sender is UserControl userControl && userControl is IDataContainer dataContainer)
                dataContainer.Highlight(false);
        }

        public void AddResizeRectangles(IEnumerable<osBase> selectedObjects)
        {
            double rectHighlightSize = 1;
            RemoveResizeRectangles();

            // Verificar si hay objetos bloqueados
            bool hasLockedObjects = selectedObjects.Any(obj => obj.Lock_movement);

            // Calcular el bounding box que contenga todos los objetos seleccionados
            Rect boundingBox = CalculateTotalBoundingBox(selectedObjects);
            if (_selectedObjectsAreVisible)
            {

                FuncionesBase.MutableRect rectBox = new FuncionesBase.MutableRect(boundingBox);
                rectBox.Left -= (float)rectHighlightSize;
                rectBox.Right += (float)rectHighlightSize;
                rectBox.Top -= (float)rectHighlightSize;
                rectBox.Bottom += (float)rectHighlightSize;

                _transformedBoundingBoxCenter = new Point(
                    boundingBox.Left + boundingBox.Width / 2,
                    boundingBox.Top + boundingBox.Height / 2
                );

                // Siempre mostrar el rectángulo de selección
                Rectangle selectionRect = CreateSelectionRectangle(rectBox, rectHighlightSize, hasLockedObjects);
                _resizeRectangles.Add(selectionRect);
                _canvas.Children.Add(selectionRect);

                // Solo agregar handles de manipulación si no hay objetos bloqueados
                if (!hasLockedObjects)
                {
                    // Load rotation cursors
                    Cursor rotationCursorRx = new Cursor(Application.GetResourceStream(
                        new Uri("pack://application:,,,/CtrEditor;component/Icons/rotationRx.cur")).Stream);
                    Cursor rotationCursorSx = new Cursor(Application.GetResourceStream(
                        new Uri("pack://application:,,,/CtrEditor;component/Icons/rotationSx.cur")).Stream);

                    // Add resize/rotation handles
                    AddResizeHandles(rectBox, 10, rotationCursorRx, rotationCursorSx);
                }
            }
        }

        private Rect CalculateTotalBoundingBox(IEnumerable<osBase> selectedObjects)
        {
            double left = double.MaxValue;
            double top = double.MaxValue;
            double right = double.MinValue;
            double bottom = double.MinValue;
            _selectedObjectsAreVisible = false;

            foreach (var obj in selectedObjects)
            {
                if (obj.VisualRepresentation != null && obj.VisualRepresentation.Visibility != Visibility.Collapsed)
                {
                    // Obtener el bounding box del objeto actual
                    Rect objectBounds = VisualTreeHelper.GetDescendantBounds(obj.VisualRepresentation);
                    GeneralTransform transform = obj.VisualRepresentation.TransformToAncestor(_canvas);
                    Rect transformedBounds = transform.TransformBounds(objectBounds);

                    // Actualizar los límites del bounding box total
                    left = Math.Min(left, transformedBounds.Left);
                    top = Math.Min(top, transformedBounds.Top);
                    right = Math.Max(right, transformedBounds.Right);
                    bottom = Math.Max(bottom, transformedBounds.Bottom);
                    _selectedObjectsAreVisible = true;
                }
            }

            return new Rect(
                new Point(left, top),
                new Point(right, bottom)
            );
        }

        private Rectangle CreateSelectionRectangle(FuncionesBase.MutableRect rectBox, double rectHighlightSize, bool hasLockedObjects = false)
        {
            if (double.IsInfinity(rectBox.Width) || double.IsInfinity(rectBox.Height) ||
                double.IsNaN(rectBox.Width) || double.IsNaN(rectBox.Height))
            {
                throw new ArgumentException("Invalid dimensions for selection rectangle.");
            }

            // Cambiar el estilo visual dependiendo si hay objetos bloqueados
            Brush strokeBrush;
            DoubleCollection dashArray;

            if (hasLockedObjects)
            {
                // Estilo para objetos bloqueados (rojo/naranja con líneas más separadas)
                strokeBrush = new SolidColorBrush(Color.FromArgb(180, 255, 140, 0)); // Naranja
                dashArray = new DoubleCollection(new double[] { 5, 3 }); // Líneas más largas
            }
            else
            {
                // Estilo normal para objetos no bloqueados (azul)
                strokeBrush = new SolidColorBrush(Color.FromArgb(180, 0, 120, 215)); // Azul
                dashArray = new DoubleCollection(new double[] { 3, 3 }); // Líneas normales
            }

            var rect = new Rectangle
            {
                Width = rectBox.Width + (rectHighlightSize * 2),
                Height = rectBox.Height + (rectHighlightSize * 2),
                Fill = Brushes.Transparent,
                Stroke = strokeBrush,
                StrokeThickness = 1.5,
                Tag = "Selection",
                IsHitTestVisible = false,
                StrokeDashArray = dashArray
            };

            Canvas.SetLeft(rect, rectBox.Left - rectHighlightSize);
            Canvas.SetTop(rect, rectBox.Top - rectHighlightSize);
            Canvas.SetZIndex(rect, ((int)ZIndexEnum.RectangulosPropiead - 1));

            return rect;
        }


        private void AddResizeHandles(FuncionesBase.MutableRect rectBox, double defaultRectSize,
            Cursor rotationCursorRx, Cursor rotationCursorSx)
        {

            // Calcular el tamaño apropiado para los manejadores basado en el tamaño del objeto
            double minObjectDimension = Math.Min(rectBox.Width, rectBox.Height);
            double rectSize = Math.Min(defaultRectSize, minObjectDimension / 3);

            // Asegurar un tamaño mínimo para los manejadores
            rectSize = Math.Max(rectSize, 6);

            // Calcular el offset para posicionar los manejadores fuera del rectángulo
            double offset = rectSize / 2;

            // Determinar cursores adaptativos según la rotación del objeto
            var cursors = GetAdaptiveCursors();

            var positions = new List<(Point Position, string Tag, Cursor Cursor, Brush Stroke)>
            {
                // Esquinas - mover hacia afuera del rectángulo
                (new Point(rectBox.Left - offset, rectBox.Top - offset), "TopLeft", Cursors.Arrow, Brushes.Gray),
                (new Point(rectBox.Right + offset, rectBox.Top - offset), "TopRight", rotationCursorRx, Brushes.Red),
                (new Point(rectBox.Left - offset, rectBox.Bottom + offset), "BottomLeft", rotationCursorSx, Brushes.DarkRed),
                (new Point(rectBox.Right + offset, rectBox.Bottom + offset), "BottomRight", cursors.ResizeBoth, Brushes.Blue),
                
                // Centros de los bordes - mover hacia afuera del rectángulo
                (new Point(rectBox.Left + rectBox.Width / 2, rectBox.Top - offset), "TopCenter", Cursors.Arrow, Brushes.Gray),
                (new Point(rectBox.Left + rectBox.Width / 2, rectBox.Bottom + offset), "BottomCenter", cursors.ResizeVertical, Brushes.Blue),
                (new Point(rectBox.Left - offset, rectBox.Top + rectBox.Height / 2), "CenterLeft", rotationCursorRx, Brushes.Red),
                (new Point(rectBox.Right + offset, rectBox.Top + rectBox.Height / 2), "CenterRight", cursors.ResizeHorizontal, Brushes.Blue)
            };

            foreach (var (Position, Tag, Cursor, Stroke) in positions)
            {
                var handle = CreateResizeHandle(rectSize, Tag, Cursor, Stroke);
                SetHandlePosition(handle, Position, rectSize);
                _resizeRectangles.Add(handle);
                _canvas.Children.Add(handle);
            }
        }

        private (Cursor ResizeHorizontal, Cursor ResizeVertical, Cursor ResizeBoth) GetAdaptiveCursors()
        {
            // Para un solo objeto o múltiples objetos con la misma rotación
            var firstObject = _selectedObjects.FirstOrDefault();
            if (firstObject == null)
                return (Cursors.SizeWE, Cursors.SizeNS, Cursors.SizeNWSE);

            double angle = Math.Abs(firstObject.Angulo % 360);

            // Si el objeto no está significativamente rotado, usar cursores estándar
            if (angle < 15 || (angle > 345 && angle < 360) ||
                (angle > 165 && angle < 195))
            {
                return (Cursors.SizeWE, Cursors.SizeNS, Cursors.SizeNWSE);
            }
            else if ((angle > 75 && angle < 105) || (angle > 255 && angle < 285))
            {
                // Objeto rotado 90 grados - intercambiar cursores
                return (Cursors.SizeNS, Cursors.SizeWE, Cursors.SizeNESW);
            }
            else if ((angle > 30 && angle < 60) || (angle > 210 && angle < 240))
            {
                // Objeto rotado aproximadamente 45 grados
                return (Cursors.SizeNESW, Cursors.SizeNWSE, Cursors.SizeAll);
            }
            else if ((angle > 120 && angle < 150) || (angle > 300 && angle < 330))
            {
                // Objeto rotado aproximadamente 135 grados
                return (Cursors.SizeNWSE, Cursors.SizeNESW, Cursors.SizeAll);
            }
            else
            {
                // Para otros ángulos, usar cursores generales
                return (Cursors.SizeAll, Cursors.SizeAll, Cursors.SizeAll);
            }
        }

        private Rectangle CreateResizeHandle(double rectSize, string tag, Cursor cursor, Brush stroke)
        {
            var handle = new Rectangle
            {
                Width = rectSize,
                Height = rectSize,
                Fill = Brushes.Transparent,
                Stroke = stroke,
                StrokeThickness = 1,
                Tag = tag,
                Cursor = cursor
            };

            handle.MouseLeftButtonDown += UserControl_MouseLeftButtonDown;
            handle.MouseMove += UserControl_MouseMove;
            handle.MouseLeftButtonUp += UserControl_MouseLeftButtonUp;
            handle.MouseLeave += ResizeRectangle_MouseLeave;

            Canvas.SetZIndex(handle, (int)ZIndexEnum.RectangulosPropiead);
            return handle;
        }

        private void SetHandlePosition(Rectangle handle, Point position, double rectSize)
        {
            if (!double.IsInfinity(position.X) && !double.IsNaN(position.X))
                Canvas.SetLeft(handle, position.X - rectSize / 2);
            if (!double.IsInfinity(position.Y) && !double.IsNaN(position.Y))
                Canvas.SetTop(handle, position.Y - rectSize / 2);
        }

        public void RemoveResizeRectangles()
        {
            if (_resizeRectangles == null || _resizeRectangles.Count == 0)
                return;

            foreach (var rect in _resizeRectangles)
            {
                _canvas.Children.Remove(rect);
            }
            _resizeRectangles.Clear();
        }

        public void MakeResizeRectanglesTransparent()
        {
            if (_resizeRectangles == null || _resizeRectangles.Count == 0)
                return;

            foreach (var rect in _resizeRectangles)
            {
                rect.Opacity = 0;
            }
        }

        public void MakeResizeRectanglesNormal()
        {
            if (_resizeRectangles == null || _resizeRectangles.Count == 0)
                return;

            foreach (var rect in _resizeRectangles)
            {
                rect.Opacity = 1;
            }
        }

        private void HandleObjectSelection(UserControl userControl, osBase datos)
        {

            PurgeDeletedObjects();
            var viewModel = _mainWindow.DataContext as MainViewModel;
            if (viewModel == null) return;

            bool isControlPressed = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);

            if (viewModel.IsMultiSelectionActive)
            {
                if (isControlPressed)
                {
                    // Deseleccionar objeto si está presionada la tecla Ctrl
                    if (_selectedObjects.Contains(datos))
                    {
                        DeselectObject(datos);
                    }
                }
                else if (!_selectedObjects.Contains(datos))
                {
                    // Seleccionar objeto si no está ya seleccionado
                    SelectObject(datos);
                }
            }
            else
            {
                // Modo selección única
                ClearSelection();
                SelectObject(datos);
            }

            viewModel.SelectedItemOsList = datos;
            UpdateSelectionVisuals();
        }

        public void SelectObject(osBase obj)
        {
            if (_mainWindow.DataContext is MainViewModel vm)
            {
                // Add new object if not already selected
                if (!_selectedObjects.Contains(obj))
                {
                    // If not in multi-selection mode, clear existing selection first
                    if (!vm.IsMultiSelectionActive)
                        ClearSelection();

                    _selectedObjects.Add(obj);
                    obj.IsSelected = true;

                    // Add highlight visual only if in multi-selection mode
                    if (vm.IsMultiSelectionActive)
                    {
                        AddSelectionHighlight(obj.VisualRepresentation);
                    }

                    UpdateSelectionVisuals();

                    // Update the view model's selection state
                    vm.NotifySelectionChanged();
                }
            }
        }

        public void DeselectObject(osBase obj)
        {
            if (_selectedObjects.Contains(obj))
            {
                _selectedObjects.Remove(obj);
                obj.IsSelected = false;
                RemoveSelectionHighlight(obj.VisualRepresentation);

                // Update the view model's selection state
                if (_mainWindow.DataContext is MainViewModel vm)
                {
                    vm.NotifySelectionChanged();
                }
            }
        }

        public void ClearSelection()
        {
            // Forzar la actualización de bindings pendientes antes de limpiar la selección
            if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null)
            {
                // Obtener el PropertyGrid del PanelEdicion y forzar actualización de bindings
                var panelEdicion = _mainWindow.PanelEdicion;
                if (panelEdicion != null && panelEdicion.IsKeyboardFocusWithin)
                {
                    // Solo forzar actualización si NO es el PLCControl el que tiene el foco
                    var plcControl = _mainWindow.PLCSim;
                    if (plcControl != null && plcControl.IsKeyboardFocusWithin)
                    {
                        System.Diagnostics.Debug.WriteLine("PLCControl tiene foco - NO forzar actualización");
                        System.IO.File.AppendAllText("c:\\temp\\debug_focus.txt", 
                            $"{DateTime.Now}: PLCControl tiene foco - NO forzar actualización\n");
                        // No forzar actualización si el PLCControl tiene el foco
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("PanelEdicion tiene foco - forzar actualización");
                        System.IO.File.AppendAllText("c:\\temp\\debug_focus.txt", 
                            $"{DateTime.Now}: PanelEdicion tiene foco - forzar actualización\n");
                        UserControlFactory.ForzarActualizacionBindings(panelEdicion.PropertyGrid);
                    }
                }
            }

            foreach (var obj in _selectedObjects.ToList())
            {
                DeselectObject(obj);
            }
            RemoveAllSelectionHighlights();
            RemoveResizeRectangles();

            if (_mainWindow.DataContext is MainViewModel viewModel2)
            {
                viewModel2.SelectedItemOsList = null;
            }
        }

        public void OnMultiSelectionModeChanged(bool isActive)
        {
            if (!isActive)
            {
                // Mantener solo el último objeto seleccionado
                if (_selectedObjects.Count > 1)
                {
                    var lastSelected = _selectedObjects.Last();
                    ClearSelection();
                    SelectObject(lastSelected);
                }
                RemoveAllSelectionHighlights();
            }
            else
            {
                UpdateAllSelectionHighlights();
            }
        }

        private void AddSelectionHighlight(UserControl userControl, bool isReference = false)
        {
            if (userControl == null) return;

            RemoveSelectionHighlight(userControl);

            Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl);
            GeneralTransform transform = userControl.TransformToAncestor(_canvas);
            Rect transformedBoundingBox = transform.TransformBounds(boundingBox);

            Rectangle highlightRect = new Rectangle
            {
                Width = transformedBoundingBox.Width,
                Height = transformedBoundingBox.Height,
                Fill = Brushes.Transparent,
                Stroke = new SolidColorBrush(isReference ?
                    Color.FromArgb(180, 128, 0, 128) :  // Purple for reference
                    Color.FromArgb(180, 255, 0, 0)),    // Red for others
                StrokeThickness = isReference ? 3 : 2,  // Más grueso para el de referencia
                Tag = "SelectionHighlight",
                IsHitTestVisible = false
            };

            Canvas.SetLeft(highlightRect, transformedBoundingBox.Left);
            Canvas.SetTop(highlightRect, transformedBoundingBox.Top);
            Canvas.SetZIndex(highlightRect, (int)ZIndexEnum.RectangulosPropiead - 1);

            _selectionHighlightPairs.Add((userControl, highlightRect));
            _canvas.Children.Add(highlightRect);
        }

        private void RemoveSelectionHighlight(UserControl userControl)
        {
            var pairsToRemove = _selectionHighlightPairs.Where(p => p.Control == userControl).ToList();
            foreach (var pair in pairsToRemove)
            {
                _canvas.Children.Remove(pair.Highlight);
                _selectionHighlightPairs.Remove(pair);
            }
        }

        public void RemoveAllSelectionHighlights()
        {
            foreach (var pair in _selectionHighlightPairs)
            {
                _canvas.Children.Remove(pair.Highlight);
            }
            _selectionHighlightPairs.Clear();
        }

        private void UpdateAllSelectionHighlights()
        {
            if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive)
            {
                RemoveAllSelectionHighlights();
                bool isFirst = true;
                foreach (var selectedObject in _selectedObjects)
                {
                    if (selectedObject.VisualRepresentation != null)
                    {
                        AddSelectionHighlight(selectedObject.VisualRepresentation, isFirst);
                        isFirst = false;
                    }
                }
            }
        }

        private void UpdateSelectionHighlights()
        {
            UpdateAllSelectionHighlights();
        }

        private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!_isDrawingCanvas)
            {
                // Verificar si hay objetos bloqueados en la selección actual
                bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);

                if (_resizeRectangles != null && _resizeRectangles.Contains(sender))
                {
                    // Si hay objetos bloqueados, no permitir redimensionamiento
                    if (hasLockedObjects)
                    {
                        e.Handled = true;
                        return;
                    }

                    // Capturar estado antes de iniciar redimensionamiento
                    CaptureUndoState();

                    _currentDraggingRectangle = sender as Rectangle;
                    _lastMousePosition = e.GetPosition(_canvas);
                    _currentDraggingRectangle.CaptureMouse();
                    _isMovingUserControl = true;
                    _startPointUserControl = e.GetPosition(_canvas);
                    e.Handled = true;
                    return;
                }

                var userControl = sender as UserControl;
                if (userControl != null && userControl.DataContext is osBase datos)
                {
                    bool isControlPressed = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);

                    // Determinar qué objetos serán afectados por el movimiento
                    List<osBase> objectsToMove = new List<osBase>();

                    if (!isControlPressed)
                    {
                        // Si no está Ctrl presionado y vamos a hacer dragging
                        if (_selectedObjects.Contains(datos))
                        {
                            // Si el objeto ya está seleccionado, vamos a mover todos los seleccionados
                            objectsToMove.AddRange(_selectedObjects);
                        }
                        else
                        {
                            // Si no está seleccionado, solo vamos a mover este objeto
                            objectsToMove.Add(datos);
                        }

                        // Verificar si alguno de los objetos a mover está bloqueado
                        bool willMoveLockedObjects = objectsToMove.Any(obj => obj.Lock_movement);

                        if (!willMoveLockedObjects)
                        {
                            // Capturar estado antes de iniciar movimiento
                            CaptureUndoStateForObjects(objectsToMove);

                            userControl.CaptureMouse();
                            _currentDraggingControl = userControl;
                            _isMovingUserControl = true;
                            InitializeDrag(e);
                        }
                    }

                    // Manejar la selección después de capturar el estado
                    HandleObjectSelection(userControl, datos);

                    // Actualizar el estado de objetos bloqueados después de la selección
                    hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);

                    if (hasLockedObjects && !isControlPressed)
                    {
                        // Si hay objetos bloqueados, no permitir el inicio del arrastre
                        e.Handled = true;
                    }
                }
            }
        }

        private void InitializeDrag(MouseButtonEventArgs e)
        {
            _isDraggingUserControl = true;
            _startPointUserControl = e.GetPosition(_canvas);
        }

        private void UserControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (_isMovingUserControl)
            {
                var currentPosition = e.GetPosition(_canvas);
                MakeResizeRectanglesTransparent();

                if (_isDraggingUserControl)
                {
                    HandleDrag(currentPosition);
                }
                else if (_currentDraggingRectangle != null)
                {
                    string resizeDirection = _currentDraggingRectangle.Tag as string;
                    if (resizeDirection != null)
                    {
                        var mode = DetermineHandleMode(resizeDirection);
                        switch (mode)
                        {
                            case HandleMode.Rotate:
                                HandleRotation(currentPosition);
                                break;
                            case HandleMode.ResizeWidth:
                            case HandleMode.ResizeHeight:
                            case HandleMode.ResizeBoth:
                                HandleResize(currentPosition, mode);
                                break;
                        }
                    }
                }
            }
        }

        private void HandleDrag(Point currentPosition)
        {
            PurgeDeletedObjects();

            // Verificar si hay objetos bloqueados antes de mover
            bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
            if (hasLockedObjects)
            {
                return; // No mover si hay objetos bloqueados
            }

            var dx = currentPosition.X - _startPointUserControl.X;
            var dy = currentPosition.Y - _startPointUserControl.Y;

            RemoveAllSelectionHighlights(); // Remover antes de mover

            foreach (var selectedObject in _selectedObjects)
            {
                var newX = Canvas.GetLeft(selectedObject.VisualRepresentation) + dx;
                var newY = Canvas.GetTop(selectedObject.VisualRepresentation) + dy;
                selectedObject.Move((float)newX, (float)newY);
            }
            _startPointUserControl = currentPosition;

            UpdateAllSelectionHighlights();
        }

        private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_isMovingUserControl)
            {
                if (sender is UserControl userControl)
                {
                    userControl.ReleaseMouseCapture();
                }
                else if (sender is Rectangle rectangle)
                {
                    rectangle.ReleaseMouseCapture();
                }

                RemoveAllSelectionHighlights(); // Remover antes de actualizar
                UpdateSelectionVisuals();
                UpdateAllSelectionHighlights();

                // Restaurar los rectángulos de selección si es necesario
                if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive)
                {
                    foreach (var selectedObject in _selectedObjects)
                    {
                        AddSelectionHighlight(selectedObject.VisualRepresentation);
                    }
                }

                _isDraggingUserControl = false;
                _isMovingUserControl = false;
                _currentDraggingRectangle = null;
                _currentResizeMode = ResizeMode.None;
                _lastAngle = 0;
            }
            MarkUnsavedChanges();
        }

        private void MarkUnsavedChanges()
        {
            if (_mainWindow.DataContext is MainViewModel viewModel)
            {
                if (_isMovingUserControl || _isDraggingUserControl)
                {
                    viewModel.HasUnsavedChanges = true;
                }
            }
        }

        private void ResizeRectangle_MouseLeave(object sender, MouseEventArgs e)
        {
            var rect = sender as Rectangle;
            if (rect != null)
            {
                rect.Fill = Brushes.Transparent;
            }
        }

        public void AddHighlightRectangles(UserControl userControl)
        {
            double rectSize = 1;
            RemoveHighlightRectangles();

            if (userControl is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase && mvBase.Show_On_This_Page)
            {
                Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl);
                GeneralTransform transform = userControl.TransformToAncestor(_canvas);
                Rect transformedBoundingBox = transform.TransformBounds(boundingBox);

                FuncionesBase.MutableRect rectBox = new FuncionesBase.MutableRect(transformedBoundingBox);
                rectBox.Left -= (float)rectSize;
                rectBox.Right += (float)rectSize;
                rectBox.Top -= (float)rectSize;
                rectBox.Bottom += (float)rectSize;

                Rectangle highlightRect = new Rectangle
                {
                    Width = rectBox.Width,
                    Height = rectBox.Height,
                    Fill = Brushes.Transparent,
                    Stroke = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)),
                    StrokeThickness = 1,
                    Tag = "Highlight",
                    IsHitTestVisible = false,
                    StrokeDashArray = new DoubleCollection(new double[] { 2, 2 })
                };

                Canvas.SetLeft(highlightRect, rectBox.Left);
                Canvas.SetTop(highlightRect, rectBox.Top); // Corregido: usando rectBox.Top en lugar de highlightRect.Top

                _highlightRectangles.Add(highlightRect);
                _canvas.Children.Add(highlightRect);
                Canvas.SetZIndex(highlightRect, ((int)ZIndexEnum.RectangulosPropiead));

                if (_timerRemoveHighlight == null)
                    _timerRemoveHighlight = new System.Threading.Timer(TimerCallbackRemoveHighlight, null, Timeout.Infinite, Timeout.Infinite);

                _timerRemoveHighlight.Change(2000, Timeout.Infinite);
            }
        }

        private void TimerCallbackRemoveHighlight(object state)
        {
            if (Application.Current != null)
            {
                Application.Current.Dispatcher.Invoke(RemoveHighlightRectangles);
            }
        }

        public void RemoveHighlightRectangles()
        {
            if (_highlightRectangles == null || _highlightRectangles.Count == 0)
                return;

            foreach (var rect in _highlightRectangles)
            {
                _canvas.Children.Remove(rect);
            }
            _highlightRectangles.Clear();
        }

        private HandleMode DetermineHandleMode(string resizeDirection)
        {
            // Si tenemos múltiples objetos seleccionados con diferentes rotaciones,
            // usar el comportamiento por defecto
            if (_selectedObjects.Count > 1)
            {
                var angles = _selectedObjects.Select(obj => Math.Abs(obj.Angulo % 360)).Distinct().ToList();
                if (angles.Count > 1) // Diferentes ángulos
                {
                    return DetermineHandleModeDefault(resizeDirection);
                }
            }

            // Para un solo objeto o múltiples objetos con la misma rotación
            var firstObject = _selectedObjects.FirstOrDefault();
            if (firstObject == null)
                return HandleMode.None;

            double angle = Math.Abs(firstObject.Angulo % 360);

            // Si el objeto no está significativamente rotado, usar el comportamiento por defecto
            if (angle < 15 || (angle > 345 && angle < 360) ||
                (angle > 75 && angle < 105) ||
                (angle > 165 && angle < 195) ||
                (angle > 255 && angle < 285))
            {
                return DetermineHandleModeDefault(resizeDirection);
            }

            // Para objetos rotados significativamente, adaptar los handles
            return DetermineHandleModeRotated(resizeDirection, angle);
        }

        private HandleMode DetermineHandleModeDefault(string resizeDirection)
        {
            return resizeDirection switch
            {
                "TopLeft" => HandleMode.None,
                "TopRight" or "BottomLeft" or "CenterLeft" => HandleMode.Rotate,
                "BottomRight" => HandleMode.ResizeBoth,
                "TopCenter" => HandleMode.None,
                "BottomCenter" => HandleMode.ResizeHeight,
                "CenterRight" => HandleMode.ResizeWidth,
                _ => HandleMode.None
            };
        }

        private HandleMode DetermineHandleModeRotated(string resizeDirection, double angle)
        {
            // Para objetos rotados, hacer que todos los handles de redimensionamiento funcionen como los corners
            // Esto es mucho más intuitivo ya que el usuario puede redimensionar en cualquier dirección
            // sin preocuparse por la orientación específica del objeto

            return resizeDirection switch
            {
                "TopLeft" => HandleMode.None,
                "TopRight" or "BottomLeft" or "CenterLeft" => HandleMode.Rotate,
                "BottomRight" or "BottomCenter" or "CenterRight" or "TopCenter" => HandleMode.ResizeBoth,
                _ => HandleMode.None
            };
        }

        private void HandleResize(Point currentPosition, HandleMode mode)
        {
            PurgeDeletedObjects();

            // Verificar si hay objetos bloqueados antes de redimensionar
            bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
            if (hasLockedObjects)
            {
                return; // No redimensionar si hay objetos bloqueados
            }

            RemoveAllSelectionHighlights(); // Remover antes de redimensionar

            foreach (var selectedObject in _selectedObjects)
            {
                bool resizeWidth = mode == HandleMode.ResizeWidth || mode == HandleMode.ResizeBoth;
                bool resizeHeight = mode == HandleMode.ResizeHeight || mode == HandleMode.ResizeBoth;
                HandleResizeForObject(selectedObject, currentPosition, resizeWidth, resizeHeight);
            }
            _startPointUserControl = currentPosition;

            UpdateAllSelectionHighlights();
        }

        private void HandleResizeForObject(osBase obj, Point currentPosition, bool activateSizeWidth, bool activateSizeHeight)
        {
            // Calcular el cambio del mouse en coordenadas del canvas
            double deltaX = currentPosition.X - _startPointUserControl.X;
            double deltaY = currentPosition.Y - _startPointUserControl.Y;

            // Inicializar variables de cambio
            double widthChange = 0;
            double heightChange = 0;

            // Si el objeto no está rotado, usar el método original
            if (Math.Abs(obj.Angulo) < 0.1) // Umbral pequeño para considerar "sin rotación"
            {
                widthChange = activateSizeWidth ? deltaX : 0;
                heightChange = activateSizeHeight ? deltaY : 0;
            }
            else
            {
                // Para objetos rotados, transformar los cambios del mouse según la orientación del objeto
                // Convertir ángulo de grados a radianes
                double angleRad = obj.Angulo * Math.PI / 180.0;

                // Calcular los componentes de cambio transformados según la rotación
                // Rotar el vector de cambio por el ángulo negativo del objeto para obtener
                // los cambios en el sistema de coordenadas local del objeto
                double cos = Math.Cos(-angleRad);
                double sin = Math.Sin(-angleRad);

                double localDeltaX = deltaX * cos - deltaY * sin;
                double localDeltaY = deltaX * sin + deltaY * cos;

                // Determinar qué componente aplicar según el tipo de redimensionamiento
                if (activateSizeWidth && activateSizeHeight)
                {
                    // Redimensionamiento proporcional - usar la componente más grande transformada
                    widthChange = localDeltaX;
                    heightChange = localDeltaY;
                }
                else if (activateSizeWidth)
                {
                    // Solo redimensionar ancho - usar componente X transformada
                    widthChange = localDeltaX;
                }
                else if (activateSizeHeight)
                {
                    // Solo redimensionar alto - usar componente Y transformada
                    heightChange = localDeltaY;
                }
            }

            obj.Resize(widthChange, heightChange);
        }

        private void HandleRotation(Point currentPosition)
        {
            PurgeDeletedObjects();

            // Verificar si hay objetos bloqueados antes de rotar
            bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
            if (hasLockedObjects)
            {
                return; // No rotar si hay objetos bloqueados
            }

            RemoveAllSelectionHighlights(); // Remover antes de rotar

            // Verificar si la tecla Shift está presionada para rotación en incrementos de 45 grados
            bool isShiftPressed = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);

            // Calcular el ángulo respecto al centro del bounding box que contiene todos los objetos seleccionados
            double deltaX = currentPosition.X - _transformedBoundingBoxCenter.X;
            double deltaY = currentPosition.Y - _transformedBoundingBoxCenter.Y;
            double angle = Math.Atan2(deltaY, deltaX) * (180 / Math.PI);

            if ((_lastAngle == 0 && angle != 0) || Math.Abs(angle - _lastAngle) > 45)
            {
                _lastAngle = (float)angle;
            }
            else
            {
                double deltaAngle = angle - _lastAngle;

                if (isShiftPressed)
                {
                    // Rotación en incrementos de 45 grados
                    // Calcular el ángulo total acumulado desde el inicio de la rotación
                    double totalAngleChange = angle - _lastAngle;

                    // Determinar a qué incremento de 45 grados corresponde
                    double snapAngle = Math.Round(totalAngleChange / 45.0) * 45.0;

                    // Solo aplicar la rotación si hay un cambio significativo (al menos 22.5 grados de movimiento)
                    if (Math.Abs(totalAngleChange) > 22.5)
                    {
                        // Calcular el cambio real que necesitamos aplicar
                        double actualRotationChange = snapAngle;

                        foreach (var selectedObject in _selectedObjects)
                        {
                            // Obtener el ángulo actual del objeto
                            double currentObjectAngle = selectedObject.Angulo;

                            // Calcular el nuevo ángulo alineado a incrementos de 45 grados
                            double targetAngle = Math.Round((currentObjectAngle + actualRotationChange) / 45.0) * 45.0;

                            // Aplicar la rotación necesaria para llegar al ángulo objetivo
                            double rotationNeeded = targetAngle - currentObjectAngle;
                            selectedObject.Rotate(rotationNeeded);
                        }

                        // Actualizar el ángulo de referencia para evitar aplicar la misma rotación múltiples veces
                        _lastAngle = (float)angle;
                    }
                }
                else
                {
                    // Rotación libre (comportamiento original)
                    foreach (var selectedObject in _selectedObjects)
                    {
                        selectedObject.Rotate(deltaAngle);
                    }
                    _lastAngle = (float)angle;
                }
            }

            UpdateAllSelectionHighlights();
        }

        public void AlignObjects(AlignmentType alignmentType)
        {
            PurgeDeletedObjects();
            if (_selectedObjects.Count <= 1) return;

            // Verificar si hay objetos bloqueados antes de alinear
            bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
            if (hasLockedObjects)
            {
                return; // No alinear si hay objetos bloqueados
            }

            // Capturar estado antes de alinear
            CaptureUndoState();

            var alignment = new ObjectAlignment(_selectedObjects, _selectedObjects.FirstOrDefault());

            switch (alignmentType)
            {
                case AlignmentType.Left:
                    alignment.AlignLeft();
                    break;
                case AlignmentType.Right:
                    alignment.AlignRight();
                    break;
                case AlignmentType.Top:
                    alignment.AlignTop();
                    break;
                case AlignmentType.Bottom:
                    alignment.AlignBottom();
                    break;
                case AlignmentType.CenterHorizontally:
                    alignment.AlignCenterHorizontally();
                    break;
                case AlignmentType.CenterVertically:
                    alignment.AlignCenterVertically();
                    break;
                case AlignmentType.DistributeHorizontally:
                    alignment.DistributeHorizontally();
                    break;
                case AlignmentType.DistributeVertically:
                    alignment.DistributeVertically();
                    break;
                case AlignmentType.EqualWidth:
                    alignment.EqualWidth();
                    break;
                case AlignmentType.EqualHeight:
                    alignment.EqualHeight();
                    break;
                case AlignmentType.EqualAngle:
                    alignment.EqualAngle();
                    break;
                case AlignmentType.JoinHorizontally:
                    alignment.JoinHorizontally();
                    break;
                case AlignmentType.JoinVertically:
                    alignment.JoinVertically();
                    break;
            }

            // Update the selection visuals after alignment
            UpdateSelectionVisuals();
        }

        public void EliminarObjetosSeleccionados()
        {
            if (_selectedObjects.Count == 0) return;

            var viewModel = _mainWindow.DataContext as MainViewModel;
            if (viewModel == null) return;

            // Verificar si hay objetos bloqueados antes de eliminar
            bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
            if (hasLockedObjects)
            {
                return; // No eliminar si hay objetos bloqueados
            }

            // Crear una copia de la lista para evitar modificaciones durante la iteración
            var objectsToRemove = _selectedObjects.ToList();

            foreach (var obj in objectsToRemove)
            {
                viewModel.RemoverObjetoSimulable(obj);
            }

            // Limpiar la selección y actualizar la interfaz
            ClearSelection();
            RemoveResizeRectangles();
            RemoveAllSelectionHighlights();

            // Ensure the property panel is cleared by explicitly setting SelectedItemOsList to null
            viewModel.SelectedItemOsList = null;

            // Actualizar el estado de cambios sin guardar
            if (viewModel != null)
            {
                viewModel.HasUnsavedChanges = true;
            }
        }

        public void StartRectangleSelection(Point startPoint)
        {
            _rectangleStart = startPoint;
            _selectionRectangle = new Rectangle
            {
                Stroke = Brushes.Blue,
                StrokeThickness = 1,
                Fill = new SolidColorBrush(Color.FromArgb(50, 0, 0, 255))
            };

            Canvas.SetLeft(_selectionRectangle, startPoint.X);
            Canvas.SetTop(_selectionRectangle, startPoint.Y);
            Canvas.SetZIndex(_selectionRectangle, (int)ZIndexEnum.RectangulosPropiead);

            _canvas.Children.Add(_selectionRectangle);
        }

        private void UpdateSelectionRectangle(Point currentPoint)
        {
            double left = Math.Min(_rectangleStart.X, currentPoint.X);
            double top = Math.Min(_rectangleStart.Y, currentPoint.Y);
            double width = Math.Abs(currentPoint.X - _rectangleStart.X);
            double height = Math.Abs(currentPoint.Y - _rectangleStart.Y);

            _selectionRectangle.Width = width;
            _selectionRectangle.Height = height;
            Canvas.SetLeft(_selectionRectangle, left);
            Canvas.SetTop(_selectionRectangle, top);
        }

        public void FinishRectangleSelection(Point currentPoint)
        {
            if (_selectionRectangle != null)
            {
                var left = Canvas.GetLeft(_selectionRectangle);
                var top = Canvas.GetTop(_selectionRectangle);
                var right = left + _selectionRectangle.Width;
                var bottom = top + _selectionRectangle.Height;
                var selectionBounds = new Rect(new Point(left, top), new Point(right, bottom));

                var itemsToProcess = _canvas.Children.OfType<UserControl>().Where(child => child is IDataContainer).ToList();

                foreach (var child in itemsToProcess)
                {
                    var childBounds = GetElementBounds(child);
                    if (selectionBounds.Contains(childBounds) || selectionBounds.IntersectsWith(childBounds))
                    {
                        if (child.DataContext is osBase osObject)
                        {
                            SelectObject(osObject);
                        }
                    }
                }

                _canvas.Children.Remove(_selectionRectangle);
                _selectionRectangle = null;

                UpdateSelectionVisuals();
            }
        }

        private Rect GetElementBounds(FrameworkElement element)
        {
            var bounds = VisualTreeHelper.GetDescendantBounds(element);
            var transform = element.TransformToAncestor(_canvas);
            return transform.TransformBounds(bounds);
        }

        public void UpdateRectangleSelection(Point currentPoint)
        {
            if (_selectionRectangle != null)
            {
                UpdateSelectionRectangle(currentPoint);
            }
        }

        // Métodos del sistema de Undo
        public void CaptureUndoState()
        {
            // Solo capturar estado si no estamos aplicando un undo y si es permitido
            if (_isApplyingUndo || !CanPerformUndo())
                return;

            // Solo capturar estado si hay objetos seleccionados
            if (_selectedObjects.Count == 0)
                return;

            if (_mainWindow.DataContext is MainViewModel viewModel)
            {
                // Capturar solo el estado de los objetos seleccionados
                var undoState = new UndoState(_selectedObjects);

                // Mantener solo los últimos MaxUndoSteps estados
                if (_undoHistory.Count >= MaxUndoSteps)
                {
                    // Convertir a lista, remover el más antiguo, y volver a crear el stack
                    var tempList = _undoHistory.ToList();
                    tempList.Reverse(); // Invertir para mantener el orden correcto
                    tempList.RemoveAt(0); // Remover el más antiguo
                    _undoHistory.Clear();
                    foreach (var state in tempList)
                    {
                        _undoHistory.Push(state);
                    }
                }

                _undoHistory.Push(undoState);
                Console.WriteLine($"Estado capturado para undo de {_selectedObjects.Count} objetos. Historial: {_undoHistory.Count} estados");
            }
        }

        // Método para capturar el estado de objetos específicos
        public void CaptureUndoStateForObjects(IEnumerable<osBase> objects)
        {
            // Solo capturar estado si no estamos aplicando un undo y si es permitido
            if (_isApplyingUndo || !CanPerformUndo())
                return;

            var objectsList = objects.ToList();
            if (objectsList.Count == 0)
                return;

            if (_mainWindow.DataContext is MainViewModel viewModel)
            {
                // Capturar solo el estado de los objetos especificados
                var undoState = new UndoState(objectsList);

                // Mantener solo los últimos MaxUndoSteps estados
                if (_undoHistory.Count >= MaxUndoSteps)
                {
                    // Convertir a lista, remover el más antiguo, y volver a crear el stack
                    var tempList = _undoHistory.ToList();
                    tempList.Reverse(); // Invertir para mantener el orden correcto
                    tempList.RemoveAt(0); // Remover el más antiguo
                    _undoHistory.Clear();
                    foreach (var state in tempList)
                    {
                        _undoHistory.Push(state);
                    }
                }

                _undoHistory.Push(undoState);
                Console.WriteLine($"Estado capturado para undo de {objectsList.Count} objetos específicos. Historial: {_undoHistory.Count} estados");
            }
        }

        public bool CanPerformUndo()
        {
            if (_mainWindow.DataContext is MainViewModel viewModel)
            {
                // Solo permitir undo si no estamos en simulación ni conectados
                return !viewModel.IsSimulationRunning && !viewModel.IsConnected;
            }
            return false;
        }

        public bool CanUndo()
        {
            return CanPerformUndo() && _undoHistory.Count > 0;
        }

        public void PerformUndo()
        {
            if (!CanUndo())
                return;

            if (_mainWindow.DataContext is MainViewModel viewModel)
            {
                _isApplyingUndo = true;

                try
                {
                    var undoState = _undoHistory.Pop();
                    Console.WriteLine($"Aplicando undo. Estados restantes: {_undoHistory.Count}");

                    // Aplicar el estado a cada objeto
                    foreach (var objectState in undoState.ObjectStates)
                    {
                        var obj = viewModel.ObjetosSimulables.FirstOrDefault(o => o.Id.Value == objectState.ObjectId);
                        if (obj != null)
                        {
                            // Aplicar solo los parámetros básicos
                            obj.Left = objectState.Left;
                            obj.Top = objectState.Top;
                            obj.Angulo = objectState.Angle;
                            obj.Ancho = objectState.Width;
                            obj.Alto = objectState.Height;

                            // Actualizar la posición visual
                            obj.OnMoveResizeRotate();
                        }
                    }

                    // Actualizar los visuales de selección
                    UpdateSelectionVisuals();

                    // Marcar como cambios sin guardar
                    viewModel.HasUnsavedChanges = true;

                    Console.WriteLine("Undo aplicado exitosamente");
                }
                finally
                {
                    _isApplyingUndo = false;
                }
            }
        }

        public void ClearUndoHistory()
        {
            _undoHistory.Clear();
            Console.WriteLine("Historial de undo limpiado");
        }

        // Método de conveniencia para obtener información del historial
        public int GetUndoHistoryCount()
        {
            return _undoHistory.Count;
        }
    }
}