#region Using
using Autofac;
using BatoirApp.Model;
using BatoirApp.MVVM.Services;
using BatoirApp.View;
using BatoirApp.View.Orders;
using BatoirApp.View.UserControls;
using BatoirApp.ViewModel;
using BatoirApp.ViewModel.Orders;
using BatoirApp.ViewModel.Products;
using Microsoft.Xaml.Behaviors;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
#endregion

namespace BatoirApp.MVVM.Behaviors
{
    public class KeyTriggerBehaviorNew : Behavior<UIElement>
    {
        #region Services

        private INavigationService _navigationService;

        #endregion

        #region Datagrid fields

        private OrderProductLine datagridCurrentItem;
        private bool IsColumnsEnabled;
        private int _lastKnownColumnIndex = 0;
        private int _previousColumnIndexThatHandleUpKey;
        private bool isEditingInProgress = false;
        private TextBox _cachedProductNameCellText;
        private AutoCompleteTextBox.Editors.AutoCompleteComboBox _cachedProductNameCell;
        private DataGrid datagrid;
        private AutoCompleteTextBox.Editors.AutoCompleteComboBox ProductNameCell;
        private TextBox ProductNameCellText;
        private HashSet<object> addedRows = new HashSet<object>();
        private Dictionary<object, bool> addedRowsWithCancelFlag = new Dictionary<object, bool>();
        private ObservableCollection<OrderProductLine> orderProductLines;

        #endregion

        #region NewOrderUserControl fields

        private bool _notesJustOpened = false;
        private NewOrderUserControlViewModel viewModel;
        private NewOrderUserControl newOrderUserControl;
        private bool CanShowOrderNote;

        #endregion

        #region ??????
        private object _originalKeySource;
        private bool IsUiThread;
        #endregion

        #region OnAttached & OnDetaching

        #region OnAttached
        protected override void OnAttached()
        {
            base.OnAttached();

            #region Services
            _navigationService = App.Container.Resolve<INavigationService>();
            #endregion

            #region Check associatedObject type
            if (AssociatedObject is FrameworkElement frameworkElement)
            {
                #region If NewOrderUserControl
                if (AssociatedObject is NewOrderUserControl)
                {

                    frameworkElement.Loaded += OnNewOrderControlLoaded;
                }
                #endregion

                #region If MainWindowView
                else if (AssociatedObject is MainWindowView)
                {
                    frameworkElement.Loaded += MainWindowLoaded;
                }
                #endregion
            }
            #endregion

        }
        #endregion

        #region OnDetaching
        protected override void OnDetaching()
        {
            base.OnDetaching();

            if (AssociatedObject is FrameworkElement frameworkElement)
            {
                ;
                // Subscribe to the Loaded event if it's a FrameworkElement
                frameworkElement.Loaded -= OnNewOrderControlLoaded;
            }
        } 
        #endregion

        #endregion

        #region MianWindow

        #region Methods
        private void MainWindowLoaded(object sender, RoutedEventArgs e)
        {
            var mainWindow = sender as MainWindowView;
            mainWindow.PreviewKeyDown += MainWindow_PreviewKeyDown;
            var topMenu = mainWindow.topMenu;
            var sellMenuItem = topMenu.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "SellMenuItem");
            var dataMenuItem = topMenu.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "DataMenuItem"); 
            sellMenuItem.Click += SellMenuItem_Click;
            dataMenuItem.Click += DataMenuItem_Click;
            

        }

        private void OrdersMenuItem_Click(object sender, RoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            var mainWindow = sender as MainWindowView;
            if (e.Key == Key.Escape)
            {
                // Get the original source of the key press
                DependencyObject source = e.OriginalSource as DependencyObject;
                
                var contentControl = FindChild<ContentControl>(Application.Current.MainWindow, "userControlContent");


                if (IsChildOf(contentControl, source))
                {
                    if (contentControl.Content is BatoirApp.ViewModel.Orders.NewOrderUserControlViewModel)
                    {
                        e.Handled = false;
                        return;
                    }
                    else if (contentControl.Content is BatoirApp.ViewModel.Orders.OrdersViewModel)
                    {
                        e.Handled = false;
                        return;
                    }
                }

                // Handle the ESC key for other cases
                var topMenu = FindChild<Menu>(mainWindow, "topMenu");
                var fileMenuItem = FindChild<MenuItem>(topMenu, "FileMenuItem");

                if (topMenu != null)
                {
                    bool isAnyMenuOpen = false;
                    foreach (MenuItem item in topMenu.Items)
                    {
                        if (item.IsSubmenuOpen)
                        {
                            isAnyMenuOpen = true;
                            item.IsSubmenuOpen = false;
                        }
                    }

                    if (!isAnyMenuOpen && fileMenuItem != null)
                    {
                        if (fileMenuItem.IsFocused)
                        {
                            var r = new ExitAppMessageBox();
                            r.ShowDialog();
                        }
                        else fileMenuItem.Focus();
                    }
                    e.Handled = true;
                }
            }
        }
        #endregion

        #region Menu

        #region Methods



        private void DataMenuItem_Click(object sender, RoutedEventArgs e)
        {
            var dataMenuItem = sender as MenuItem;
            if (dataMenuItem != null)
            {
                foreach (var subMenuItem in dataMenuItem.Items.OfType<MenuItem>())
                {
                    if (subMenuItem.Name == "ProductsSubMenuItem")
                    {
                        _navigationService.NavigateTo<ProductsListViewModel>();
                        var parentMenu = dataMenuItem.Parent as Menu;
                        var newOrderMenuItem = dataMenuItem.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "NewOrderMenuItem");
                        newOrderMenuItem?.Focus();
                    }
                    else if (subMenuItem.Name == "SubMenuItem2")
                    {
                        MessageBox.Show("SubMenuItem2 clicked");
                    }
                }
            }
        }

        private void SellMenuItem_Click(object sender, RoutedEventArgs e)
        {
            var sellMenuItem = sender as MenuItem;

            if (sellMenuItem != null)
            {

                if (e.OriginalSource is MenuItem clickedItem)
                {
                    switch (clickedItem.Name)
                    {
                        case "NewOrderMenuItem":
                            var parentMenu = sellMenuItem.Parent as Menu;
                            var newOrderMenuItem = sellMenuItem.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "NewOrderMenuItem");
                            newOrderMenuItem?.Focus();
                            App.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                _navigationService.NavigateTo<NewOrderUserControlViewModel>();
                                newOrderMenuItem?.Focus();
                            }), System.Windows.Threading.DispatcherPriority.Input);
                            break;

                        case "OrdersMenuItem":
                            _navigationService.NavigateTo<OrdersViewModel>();
                            break;

                            // Add other cases if there are additional submenus under SellMenuItem
                    }
                }
            }
        }
        #endregion

        #endregion

        #endregion

        #region NewOrderControl

        #region Main newOrderControl

        private void OnNewOrderControlLoaded(object sender, RoutedEventArgs e)
        {
            newOrderUserControl = sender as NewOrderUserControl;
            viewModel = newOrderUserControl.DataContext as NewOrderUserControlViewModel;
            datagrid = newOrderUserControl.itemsInNewOrderDatagrid;
            if (datagrid != null)
            {
                datagrid.PreviewKeyDown += Datagrid_PreviewKeyDown;
                datagrid.CellEditEnding += Datagrid_CellEditEnding;
                datagrid.PreparingCellForEdit += Datagrid_PreparingCellForEdit;
                datagrid.SelectedCellsChanged += Datagrid_SelectedCellsChanged;

            }

            newOrderUserControl.KeyDown += NewOrderUserControl_KeyDown;
            newOrderUserControl.ClientTextBox.Focus();
            newOrderUserControl.ClientTextBox.PreviewLostKeyboardFocus += ClientTextBox_PreviewLostKeyboardFocus;
            newOrderUserControl.ClientTextBox.KeyDown += (sender, args) =>
            {
                if (args.Key == Key.Enter)
                {
                    if (datagrid.Items.Count > 0)
                    {
                        if (datagrid.Items.Count > 0)
                        {
                            datagrid.Focus();
                            datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[0], datagrid.Columns[_previousColumnIndexThatHandleUpKey]);
                            args.Handled = true;
                            //datagrid.ScrollIntoView(datagrid.Items[0], datagrid.Columns[0]);
                        }
                    }
                    else
                    {
                        if (viewModel.SelectedCustomer != null)
                        {
                            //var orderLines = datagrid.ItemsSource as ObservableCollection<OrderProductLine>;
                            //orderLines.Add(new OrderProductLine { });
                            orderProductLines = datagrid.ItemsSource as ObservableCollection<OrderProductLine>;
                            orderProductLines.Add(new OrderProductLine { });
                            datagrid.UpdateLayout();
                            datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[0], datagrid.Columns[1]);
                            datagrid.Focus();
                            datagrid.BeginEdit();
                            ProductNameCell = FindChild<AutoCompleteTextBox.Editors.AutoCompleteComboBox>(datagrid, "ProductNameCell");
                            ProductNameCellText = FindChild<TextBox>(ProductNameCell, "PART_Editor");
                            _cachedProductNameCell = ProductNameCell;
                            _cachedProductNameCellText = ProductNameCellText;
                            ProductNameCellText.Focus();
                        }
                    }
                }
                else if (args.Key == Key.Escape)
                {
                    if (datagrid.Items.Count > 0)
                    {
                        datagrid.Focus();
                        datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[0], datagrid.Columns[_previousColumnIndexThatHandleUpKey]);
                        //datagrid.ScrollIntoView(datagrid.Items[0], datagrid.Columns[0]);
                    }
                    else
                    {
                        _navigationService.NavigateTo<MainWindowViewModel>();
                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            var mainWindow = Application.Current.Windows.OfType<MainWindowView>().FirstOrDefault();
                            if (mainWindow != null)
                            {
                                var topMenu = mainWindow.topMenu;
                                var sellMenuItem = topMenu.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "SellMenuItem");

                                if (sellMenuItem != null)
                                {
                                    var newOrderMenuItem = sellMenuItem.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "NewOrderMenuItem");
                                    if (newOrderMenuItem != null)
                                    {
                                        mainWindow.Focus();
                                        sellMenuItem.IsSubmenuOpen = true;
                                        newOrderMenuItem.Focus();

                                    }
                                }
                            }
                        }), System.Windows.Threading.DispatcherPriority.Input);
                    }
                }
            };

            newOrderUserControl.DeleteConfirmationBox.ConfirmationResult += (s, confirmed) =>
            {
                var currentItem = datagridCurrentItem;
                if (confirmed)
                {
                    foreach (UIElement element in newOrderUserControl.MainGrid.Children) // Adjust MainGrid to your parent container
                    {
                        // Check if the element is not the DeleteConfirmationBox
                        if (element != newOrderUserControl.DeleteConfirmationBox)
                        {
                            element.IsEnabled = true;
                        }
                    }
                    if (currentItem != null)
                    {
                        orderProductLines.Remove(currentItem as OrderProductLine);
                        datagrid.SelectedCells.Clear();
                        var cellInfo = new DataGridCellInfo(datagrid.Items[0], datagrid.Columns[1]);
                        datagrid.SelectedCells.Add(cellInfo);
                        datagrid.Focus();
                        Keyboard.Focus(datagrid);
                        datagrid.CurrentCell = cellInfo;
                    }
                    // Reset row background if needed
                    var row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(currentItem);
                    if (row != null)
                    {
                        row.Background = new SolidColorBrush(System.Windows.Media.Colors.White);
                    }

                }
                else
                {
                    foreach (UIElement element in newOrderUserControl.MainGrid.Children) // Adjust MainGrid to your parent container
                    {
                        // Check if the element is not the DeleteConfirmationBox
                        if (element != newOrderUserControl.DeleteConfirmationBox)
                        {
                            element.IsEnabled = true;
                        }
                    }
                    datagrid.SelectedCells.Clear();
                    var cellInfo = new DataGridCellInfo(datagrid.Items[0], datagrid.Columns[1]);
                    datagrid.SelectedCells.Add(cellInfo);
                    datagrid.Focus();
                    Keyboard.Focus(datagrid);
                    datagrid.CurrentCell = cellInfo;
                    var row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(currentItem);
                    if (row != null)
                    {
                        row.Background = new SolidColorBrush(System.Windows.Media.Colors.White);
                    }
                }

            };
        }

        private void NewOrderUserControl_KeyDown(object sender, KeyEventArgs e)
        {

            if ((Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.N))
            {
                if (CanShowOrderNote)
                {
                    if (datagrid.Items.Count > 0)
                    {
                        if (newOrderUserControl.NotesSection.Visibility == Visibility.Collapsed)
                        {
                            _originalKeySource = e.OriginalSource;
                            newOrderUserControl.NotesSection.Visibility = Visibility.Visible;
                            newOrderUserControl.OrderNotesTextBox.Focus();
                            newOrderUserControl.ClientTextBoxGrid.IsEnabled = false;
                            newOrderUserControl.OrderTotalStackPanel.IsEnabled = false;
                            newOrderUserControl.itemsInNewOrderDatagrid.IsEnabled = false;


                        }
                        else if (newOrderUserControl.NotesSection.Visibility == Visibility.Visible)
                        {
                            newOrderUserControl.NotesSection.Visibility = Visibility.Collapsed;
                            newOrderUserControl.ClientTextBoxGrid.IsEnabled = true;
                            newOrderUserControl.OrderTotalStackPanel.IsEnabled = true;
                            newOrderUserControl.itemsInNewOrderDatagrid.IsEnabled = true;
                            if (IsChildOf(newOrderUserControl, _originalKeySource as DependencyObject))
                            {
                                (_originalKeySource as UIElement)?.Focus();
                            }
                        }
                    }
                    else return;
                }


            }
            else if (e.SystemKey == Key.F10)
            {
                if (datagrid.Items.Count >= 1)
                {
                    // Show confirmation dialog
                    MessageBoxResult result = MessageBox.Show(
                        "Are you sure you want to cancel the order?",
                        "Cancel Order Confirmation",
                        MessageBoxButton.YesNo,
                        MessageBoxImage.Question);

                    // Check the result and act accordingly
                    if (result == MessageBoxResult.Yes)
                    {
                        
                        _navigationService.NavigateTo<MainWindowViewModel>();
                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            var mainWindow = Application.Current.Windows.OfType<MainWindowView>().FirstOrDefault();
                            if (mainWindow != null)
                            {
                                var topMenu = mainWindow.topMenu;
                                var sellMenuItem = topMenu.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "SellMenuItem");

                                if (sellMenuItem != null)
                                {
                                    var newOrderMenuItem = sellMenuItem.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == "NewOrderMenuItem");
                                    if (newOrderMenuItem != null)
                                    {
                                        mainWindow.Focus();
                                        sellMenuItem.Focus();
                                        sellMenuItem.IsSubmenuOpen = true;
                                        newOrderMenuItem.Focus();

                                    }
                                }
                            }
                        }), System.Windows.Threading.DispatcherPriority.Input);
                    }
                    else
                    {
                        return;
                    }
                }
            }
        }

        private void ClientTextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            var clientTextBox = sender as AutoCompleteTextBox.Editors.AutoCompleteComboBox;
            var enteredClient = clientTextBox?.Text;
            var newOrderControl = FindParent<NewOrderUserControl>(clientTextBox);
            var viewModel = newOrderControl?.DataContext as NewOrderUserControlViewModel;

            if (Keyboard.IsKeyDown(Key.Escape))
            {
                e.Handled = false;
                return;
            }

            if (string.IsNullOrWhiteSpace(enteredClient) ||
                viewModel.AvailableCustomers.FirstOrDefault(c => c.FirstName.Equals(enteredClient, StringComparison.InvariantCultureIgnoreCase)) == null)
            {
                e.Handled = true;
            }

        } 

        #endregion

        #region Datagrid

        private void Datagrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
        {
            if (datagrid.CurrentColumn != null)
            {
                _lastKnownColumnIndex = datagrid.Columns.IndexOf(datagrid.CurrentColumn);
            }
        }

        private void Datagrid_PreparingCellForEdit(object? sender, DataGridPreparingCellForEditEventArgs e)
        {
            var orderLines = datagrid.ItemsSource as ObservableCollection<OrderProductLine>;
            if (e.Column.Header.ToString() == "Quantity")
            {
                var contentPresenter = e.EditingElement as ContentPresenter;
                var editingTextBox = new TextBox();
                editingTextBox = FindVisualChild<TextBox>(contentPresenter);

                if (editingTextBox != null)
                {
                    editingTextBox.Focus();
                    editingTextBox.SelectAll(); // Select all text in the TextBox
                }
            }
        }

        private void Datagrid_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            var view = AssociatedObject as NewOrderUserControl;
            var viewModel = view.DataContext as NewOrderUserControlViewModel;


            datagridCurrentItem = datagrid.CurrentItem as OrderProductLine;
            var currentCellInfo = datagrid.CurrentCell;
            var row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(currentCellInfo.Item);
            var dataGridCell = GetCell(datagrid, row, datagrid.Columns.IndexOf(currentCellInfo.Column));
            var dataGrid = FindParent<DataGrid>(dataGridCell);
            var currentColumn = datagrid.CurrentCell.Column;

            if (dataGridCell.IsEditing)
            {
                CanShowOrderNote = false;
                if (e.Key == Key.Right)
                {
                    if (IsColumnsEnabled)
                    {
                        //MoveToNextCellWithCurrentCellInfo(dataGrid, currentCellInfo);
                    }
                }
            }
            else // !dataGridCell.IsEditing
            {
                CanShowOrderNote = true;
                if (Keyboard.Modifiers == ModifierKeys.Control)
                {
                    // If Control is pressed, do not process the 'N' key for editing
                    if (e.Key == Key.N)
                    {
                        // Optionally handle the Control + N case here
                        return; // Exit early if Control + N is pressed
                    }
                }
                if (IsEditingKey(e.Key))
                {
                    if (datagrid.CurrentColumn.Header.ToString() == "Name")
                    {
                        if (currentColumn is DataGridTemplateColumn && datagrid.Columns.IndexOf(currentColumn) == 1)
                        {
                            // Begin editing the cell
                            datagrid.BeginEdit();

                            // Find the AutoCompleteComboBox in the current DataGridCell
                            var autoCompleteComboBox = FindChild<AutoCompleteTextBox.Editors.AutoCompleteComboBox>(dataGridCell, "ProductNameCell");

                            // Focus the AutoCompleteComboBox if found
                            if (autoCompleteComboBox != null)
                            {
                                autoCompleteComboBox.Focus();
                                autoCompleteComboBox.Text = "";
                                dataGrid.BeginEdit();
                            }
                        }

                    }
                    else if (datagrid.CurrentColumn.Header.ToString() == "Quantity")
                    {
                        #region Begin edit the Quantity cell textbox

                        if (!dataGridCell.IsEditing)
                        {
                            dataGrid.BeginEdit();
                            var QuantityTextBox = FindChild<TextBox>(dataGridCell, "QuantityTextBox");
                            if (QuantityTextBox != null)
                            {
                                QuantityTextBox.Focus();
                                QuantityTextBox.Text = "";
                                dataGrid.BeginEdit();
                            }
                        }
                        #endregion
                    }
                }
                else if (e.Key == Key.Insert)
                {
                    #region Focus on product name cell and beging editing
                    var datagrid = sender as DataGrid;
                    datagrid.SelectedCells.Clear();
                    var currentItem = datagrid.CurrentItem;
                    if (addedRowsWithCancelFlag.ContainsKey(currentItem))
                    {

                        var newOrderProductLine = new OrderProductLine { };
                        orderProductLines.Add(newOrderProductLine);
                        datagrid.ScrollIntoView(newOrderProductLine);
                        int rowIndex = datagrid.Items.IndexOf(newOrderProductLine);
                        int columnIndex = GetColumnIndexByHeader(datagrid, "Name");
                        datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[rowIndex], datagrid.Columns[columnIndex]);

                        var currentCellInfo1 = datagrid.CurrentCell;
                        var row1 = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(currentCellInfo1.Item);
                        var dataGridCell1 = GetCell(datagrid, row1, datagrid.Columns.IndexOf(currentCellInfo1.Column));
                        var dataGrid1 = FindParent<DataGrid>(dataGridCell1);

                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            // Start editing mode
                            datagrid.BeginEdit();

                            // Attempt to find the AutoCompleteComboBox now that the cell is in edit mode
                            var autoCompleteComboBox = FindChild<AutoCompleteTextBox.Editors.AutoCompleteComboBox>(dataGridCell1, "ProductNameCell");

                            // If the AutoCompleteComboBox was found, focus and clear its text
                            if (autoCompleteComboBox != null)
                            {
                                autoCompleteComboBox.Focus();
                                autoCompleteComboBox.Text = "";
                            }
                            isEditingInProgress = false;
                        }), System.Windows.Threading.DispatcherPriority.Render);
                    }
                    #endregion
                }
                else if (e.Key == Key.Up)
                {
                    if (datagrid.CurrentItem == datagrid.Items[0])
                    {
                        if (addedRowsWithCancelFlag.ContainsKey(datagrid.CurrentItem))
                        {
                            _previousColumnIndexThatHandleUpKey = _lastKnownColumnIndex;
                            newOrderUserControl.ClientTextBox.Focus();
                        }
                    }
                }
                else if (e.Key == Key.Delete)
                {
                    var currentRow = row;
                    if (datagrid.Items.Count > 1)
                    {
                        if (currentRow != null)
                        {
                            newOrderUserControl.DeleteConfirmationBox.Visibility = Visibility.Visible;
                            newOrderUserControl.DeleteConfirmationBox.NoButton.Focus();
                            // Optionally highlight the row to be deleted
                            row.Background = new SolidColorBrush(System.Windows.Media.Colors.MediumVioletRed);
                            e.Handled = true;
                            foreach (UIElement element in newOrderUserControl.MainGrid.Children) // Adjust MainGrid to your parent container
                            {
                                // Check if the element is not the DeleteConfirmationBox
                                if (element != newOrderUserControl.DeleteConfirmationBox)
                                {
                                    element.IsEnabled = false;
                                }
                            }
                        }

                    }
                }
                else if (e.Key == Key.Escape)
                {
                    
                    viewModel.OpenOrderPaymentPopupWindowCommand.Execute(null); 
                }
            }
        }

        private void Datagrid_CellEditEnding(object? sender, DataGridCellEditEndingEventArgs e)
        {


            var editingTextBox = new TextBox();
            var contentPresenter = e.EditingElement as ContentPresenter;

            if (e.EditingElement is not TextBox)
            {
                editingTextBox = FindVisualChild<TextBox>(contentPresenter);
            }

            if (e.EditAction == DataGridEditAction.Commit)
            {
                var editedRow = e.Row.Item;
                var currentHeaderName = e.Column.Header.ToString();

                //if (addedRows.Contains(editedRow))
                if (addedRowsWithCancelFlag.ContainsKey(editedRow))
                {
                    if (currentHeaderName == "Name")
                    {
                        if (string.IsNullOrWhiteSpace(editingTextBox?.Text) ||
                             viewModel.AvailableProducts.FirstOrDefault(c => c.ProductName.Equals(editingTextBox.Text, StringComparison.InvariantCultureIgnoreCase)) == null)
                        {
                            DisableColumns(datagrid, new string[] { "Quantity", "Q/U", "Price" });
                            e.Cancel = true;
                            Dispatcher.BeginInvoke(new Action(() =>
                            {
                                ProductNameCellText?.Focus();
                            }), System.Windows.Threading.DispatcherPriority.Input);
                        }
                        else
                        {
                            #region Setting orderline product to the selected product in the viewmodel that comes from the xaml
                            var orderLine = e.Row.Item as OrderProductLine;
                            var selectedProduct = viewModel.AvailableProducts
                                 .FirstOrDefault(p => p.ProductName.Equals(editingTextBox.Text, StringComparison.InvariantCultureIgnoreCase));
                            orderLine.Product = selectedProduct;
                            orderLine.ProductId = selectedProduct.ProductId;
                            orderLine.ProductName = selectedProduct.ProductName;
                            orderLine.Price = selectedProduct.Price;
                            orderLine.QuantityPerUnit = selectedProduct.QuantityPerUnit;
                            #endregion


                            EnableColumns(datagrid, new string[] { "Quantity", "Q/U", "Price" });
                            int currentRowIndex = datagrid.Items.IndexOf(e.Row.Item);
                            int currentColumnIndex = datagrid.Columns.IndexOf(e.Column);

                            // Use BeginInvoke to ensure this runs after the current cell edit operation is complete
                            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                // Keep the current cell selected
                                datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[currentRowIndex], datagrid.Columns[currentColumnIndex]);
                                datagrid.SelectedCells.Clear();
                                datagrid.SelectedCells.Add(datagrid.CurrentCell);

                                // Ensure the cell gets focus
                                DataGridCell cell = GetCell(datagrid, e.Row, currentColumnIndex);
                                if (cell != null)
                                {
                                    cell.Focus();
                                    Keyboard.Focus(cell);
                                }

                                // If you want to allow editing immediately, you can call BeginEdit
                                // datagrid.BeginEdit();
                            }), System.Windows.Threading.DispatcherPriority.Input);
                        }
                    }
                    else
                    {
                        int currentRowIndex = datagrid.Items.IndexOf(e.Row.Item);
                        int currentColumnIndex = datagrid.Columns.IndexOf(e.Column);

                        // Use BeginInvoke to ensure this runs after the current cell edit operation is complete
                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            // Keep the current cell selected
                            datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[currentRowIndex], datagrid.Columns[currentColumnIndex]);
                            datagrid.SelectedCells.Clear();
                            datagrid.SelectedCells.Add(datagrid.CurrentCell);

                            // Ensure the cell gets focus
                            DataGridCell cell = GetCell(datagrid, e.Row, currentColumnIndex);
                            if (cell != null)
                            {
                                cell.Focus();
                                Keyboard.Focus(cell);
                            }

                            // If you want to allow editing immediately, you can call BeginEdit
                            // datagrid.BeginEdit();
                        }), System.Windows.Threading.DispatcherPriority.Input);
                    }
                }
                // Else not contained
                else
                {
                    if (currentHeaderName == "Name")
                    {
                        if (string.IsNullOrWhiteSpace(editingTextBox?.Text) ||
                viewModel.AvailableProducts.FirstOrDefault(c => c.ProductName.Equals(editingTextBox.Text, StringComparison.InvariantCultureIgnoreCase)) == null)
                        {
                            var productNameCellText = FindChild<TextBox>(datagrid, "PART_Editor");
                            _cachedProductNameCellText = productNameCellText;
                            DisableColumns(datagrid, new string[] { "Quantity", "Q/U", "Price" });
                            e.Cancel = true;
                            Dispatcher.BeginInvoke(new Action(() =>
                            {
                                ProductNameCellText?.Focus();
                            }), System.Windows.Threading.DispatcherPriority.Input);
                        }
                        else
                        {
                            #region Setting orderline product to the selected product in the viewmodel that comes from the xaml
                            var orderLine = e.Row.Item as OrderProductLine;
                            var selectedProduct = viewModel.AvailableProducts
                                 .FirstOrDefault(p => p.ProductName.Equals(editingTextBox.Text, StringComparison.InvariantCultureIgnoreCase));
                            orderLine.Product = selectedProduct;
                            orderLine.ProductId = selectedProduct.ProductId;
                            orderLine.ProductName = selectedProduct.ProductName;
                            orderLine.Price = selectedProduct.Price;
                            orderLine.QuantityPerUnit = selectedProduct.QuantityPerUnit;
                            orderLine.Quantity = default(int);

                            #endregion

                            EnableColumns(datagrid, new string[] { "Quantity", "Q/U", "Price" });
                            MoveToNextCell(datagrid, e); // frist one
                            //var currentCellInfo = datagrid.CurrentCell;
                            //var row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(currentCellInfo.Item);
                            //var dataGridCell = GetCell(datagrid, row, datagrid.Columns.IndexOf(currentCellInfo.Column));
                            //var dataGrid = FindParent<DataGrid>(dataGridCell);
                            //if (!dataGridCell.IsEditing)
                            //{
                            //    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                            //    {
                            //        dataGrid.BeginEdit();
                            //        var QuantityTextBox = FindChild<TextBox>(dataGridCell, "QuantityTextBox");
                            //        if (QuantityTextBox != null)
                            //        {
                            //            QuantityTextBox.Focus();
                            //            QuantityTextBox.Text = "";
                            //            dataGrid.BeginEdit();
                            //        }

                            //    }), System.Windows.Threading.DispatcherPriority.Render);

                            //}
                        }
                    }
                    else if (currentHeaderName == "Price")
                    {
                        if (!isEditingInProgress)
                        {
                            //addedRows.Add(editedRow);
                            addedRowsWithCancelFlag.Add(editedRow, false);
                            //FocusOnCell(datagrid, e.Row.AlternationIndex, 4);
                        }

                    }
                    else if (currentHeaderName == "Quantity")
                    {
                        if (!isEditingInProgress)
                        {
                            if (string.IsNullOrWhiteSpace(editingTextBox?.Text))
                            {
                                e.Cancel = true;
                            }
                            else
                            {

                                MoveToNextCell(datagrid, e);
                            }
                        }
                    }
                    else
                    {
                        if (!isEditingInProgress)
                        {
                            MoveToNextCell(datagrid, e);
                        }
                    }
                }

            }
            else if (e.EditAction == DataGridEditAction.Cancel)
            {
                var editedRow = e.Row.Item;
                var currentHeaderName = e.Column.Header.ToString();
                if (currentHeaderName == "Name")
                {
                    int currentRowIndex = e.Row.GetIndex();
                    int lastRowIndex = datagrid.Items.Count - 1;
                    if (currentRowIndex == 0)
                    {
                        e.Cancel = true;
                    }
                    else if (addedRowsWithCancelFlag.ContainsKey(editedRow))
                    {
                        // If the flag is false, prevent canceling the row
                        if (!addedRowsWithCancelFlag[editedRow])
                        {
                            e.Cancel = true; // Prevent canceling
                        }
                        else
                        {
                            // Allow canceling
                            e.Cancel = false;
                        }
                    }
                    else
                    {
                        e.Cancel = false;
                        orderProductLines.RemoveAt(orderProductLines.Count - 1);
                        datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[0], datagrid.Columns[1]);
                        datagrid.SelectedCells.Clear();
                        datagrid.SelectedCells.Add(datagrid.CurrentCell);

                    }

                }
                else
                {
                    if (!addedRowsWithCancelFlag.ContainsKey(editedRow))
                    {
                        isEditingInProgress = true;
                        int currentRowIndex = datagrid.Items.IndexOf(datagrid.CurrentItem);
                        datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[currentRowIndex], datagrid.Columns[1]);
                        var currentCellInfo = datagrid.CurrentCell;
                        var row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(currentCellInfo.Item);
                        var dataGridCell = GetCell(datagrid, row, datagrid.Columns.IndexOf(currentCellInfo.Column));
                        var dataGrid = FindParent<DataGrid>(dataGridCell);
                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            // Start editing mode
                            datagrid.BeginEdit();

                            // Attempt to find the AutoCompleteComboBox now that the cell is in edit mode
                            var autoCompleteComboBox = FindChild<AutoCompleteTextBox.Editors.AutoCompleteComboBox>(dataGridCell, "ProductNameCell");

                            // If the AutoCompleteComboBox was found, focus and clear its text
                            if (autoCompleteComboBox != null)
                            {
                                autoCompleteComboBox.Focus();
                                autoCompleteComboBox.Text = "";
                            }
                            isEditingInProgress = false;
                        }), System.Windows.Threading.DispatcherPriority.Render);
                    }
                    else
                    {


                    }
                }
            }
        }

        private void ProductNameCell_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            var textbox = sender as TextBox;
            var enteredProduct = textbox?.Text;
            var newOrderControl = FindParent<NewOrderUserControl>(textbox);
            if (string.IsNullOrWhiteSpace(enteredProduct) ||
                viewModel.AvailableProducts.FirstOrDefault(c => c.ProductName.Equals(enteredProduct, StringComparison.InvariantCultureIgnoreCase)) == null)
            {
                e.Handled = true;
            }
        }

        #endregion

        #endregion

        #region Helper methods
        private void MoveToNextCell(DataGrid datagrid, DataGridCellEditEndingEventArgs e)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                int currentRowIndex = datagrid.Items.IndexOf(e.Row.Item);
                int currentColumnIndex = datagrid.Columns.IndexOf(e.Column);
                if (currentColumnIndex + 1 < datagrid.Columns.Count)
                {
                    datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[currentRowIndex], datagrid.Columns[currentColumnIndex + 1]);
                    datagrid.BeginEdit();
                }
            }), System.Windows.Threading.DispatcherPriority.Input);
            //if (Application.Current.Dispatcher.CheckAccess())
            //{
            //    int currentRowIndex = datagrid.Items.IndexOf(e.Row.Item);
            //    int currentColumnIndex = datagrid.Columns.IndexOf(e.Column);
            //    if (currentColumnIndex + 1 < datagrid.Columns.Count)
            //    {
            //        datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[currentRowIndex], datagrid.Columns[currentColumnIndex + 1]);
            //        datagrid.BeginEdit();
            //    }
            //}
            //else
            //{

            //    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            //    {
            //        int currentRowIndex = datagrid.Items.IndexOf(e.Row.Item);
            //        int currentColumnIndex = datagrid.Columns.IndexOf(e.Column);
            //        if (currentColumnIndex + 1 < datagrid.Columns.Count)
            //        {
            //            datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[currentRowIndex], datagrid.Columns[currentColumnIndex + 1]);
            //            datagrid.BeginEdit();
            //        }
            //    }), System.Windows.Threading.DispatcherPriority.Input);
            //}
        }

        private bool DisableColumns(DataGrid datagrid, string[] columnHeaders)
        {
            foreach (var columnHeader in columnHeaders)
            {
                var column = datagrid.Columns.FirstOrDefault(c => c.Header.ToString() == columnHeader);
                if (column != null)
                {
                    // Disable the column (You may need to adjust this logic based on your requirements)
                    column.IsReadOnly = true; // Set to read-only instead of IsEnabled
                }
            }
            return IsColumnsEnabled = false;
        }

        private bool EnableColumns(DataGrid datagrid, string[] columnHeaders)
        {
            foreach (var columnHeader in columnHeaders)
            {
                var column = datagrid.Columns.FirstOrDefault(c => c.Header.ToString() == columnHeader);
                if (column != null)
                {
                    // Enable the column
                    column.IsReadOnly = false;
                }
            }
            return IsColumnsEnabled = true;
        }

        private T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
        {
            // Confirm parent is valid
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                if (child is T childType && !string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        foundChild = (T)child;
                        break;
                    }
                }

                // Recursively drill down the tree
                foundChild = FindChild<T>(child, childName);
                if (foundChild != null) break;
            }

            return foundChild;
        }

        private MenuItem FindMenuItem(MenuItem parent, string name)
        {
            return parent.Items.OfType<MenuItem>().FirstOrDefault(item => item.Name == name);
        }
        
        private T FindParent<T>(DependencyObject child) where T : DependencyObject
        {
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);
            if (parentObject == null) return null;
            if (parentObject is T parent) return parent;
            return FindParent<T>(parentObject);
        }
        
        private T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child is T childOfType)
                {
                    return childOfType;
                }
                else
                {
                    T childItem = FindVisualChild<T>(child);
                    if (childItem != null)
                    {
                        return childItem;
                    }
                }
            }
            return null;
        }
        
        public void FocusOnCell(DataGrid dataGrid, int rowIndex, int columnIndex)
        {
            // Ensure the row index and column index are valid
            if (rowIndex < 0 || rowIndex >= dataGrid.Items.Count || columnIndex < 0 || columnIndex >= dataGrid.Columns.Count)
                return;

            // Scroll the DataGrid so the row is visible
            dataGrid.ScrollIntoView(dataGrid.Items[rowIndex]);

            // Get the DataGridRow
            DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex);
            if (row == null)
            {
                // Try to bring the row into view and generate its container
                dataGrid.UpdateLayout();
                row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex);
            }

            if (row != null)
            {
                // Get the specific cell from the row
                DataGridCell cell = GetCell(dataGrid, row, columnIndex);
                if (cell != null)
                {
                    // Set focus on the cell
                    dataGrid.BeginEdit(); // Start editing mode
                                          // Use Dispatcher to set focus to the cell
                    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        cell.Focus(); // Focus the cell
                        Keyboard.Focus(cell); // Ensure keyboard focus is set
                    }), System.Windows.Threading.DispatcherPriority.Input);
                }
            }
        }
        
        public DataGridCell GetCell(DataGrid dataGrid, DataGridRow row, int columnIndex)
        {
            DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);

            // Try to get the cell directly from the presenter
            DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
            if (cell == null)
            {
                // If the cell is null, force the cell to be generated by scrolling it into view
                dataGrid.ScrollIntoView(row, dataGrid.Columns[columnIndex]);
                cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
            }
            return cell;
        }
        
        public T GetVisualChild<T>(Visual parent) where T : Visual
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
            {
                Visual child = (Visual)VisualTreeHelper.GetChild(parent, i);
                if (child != null && child is T)
                {
                    return (T)child;
                }
                else
                {
                    T childOfChild = GetVisualChild<T>(child);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }
        
        private bool IsEditingKey(Key key)
        {
            // Define which keys should trigger the editing
            return key >= Key.A && key <= Key.Z || // Letters
                   key >= Key.D0 && key <= Key.D9 || // Numbers (Top row)
                   key >= Key.NumPad0 && key <= Key.NumPad9 || // Numbers (NumPad)
                   key == Key.Space; // Space
        }

        public void SelectCell(DataGrid dataGrid, int rowIndex, int columnIndex)
        {
            // Ensure the row index and column index are valid
            if (rowIndex < 0 || rowIndex >= dataGrid.Items.Count || columnIndex < 0 || columnIndex >= dataGrid.Columns.Count)
                return;

            // Scroll the DataGrid so the row is visible
            dataGrid.ScrollIntoView(dataGrid.Items[rowIndex]);

            // Clear any previously selected cells
            dataGrid.SelectedCells.Clear();

            // Create a DataGridCellInfo for the specified cell
            var cellInfo = new DataGridCellInfo(dataGrid.Items[rowIndex], dataGrid.Columns[columnIndex]);


            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {


                dataGrid.SelectedCells.Add(cellInfo);
                dataGrid.Focus();
                Keyboard.Focus(dataGrid);
                dataGrid.CurrentCell = cellInfo;
            }), System.Windows.Threading.DispatcherPriority.Input);

        }
       
        private int GetColumnIndexByHeader(DataGrid datagrid, string headerName)
        {
            for (int i = 0; i < datagrid.Columns.Count; i++)
            {
                if (datagrid.Columns[i].Header.ToString() == headerName)
                {
                    return i; // Return the index if the header matches
                }
            }
            return -1; // Return -1 if no match is found
        }
        
        private void MoveToNextCellWithCurrentCellInfo(DataGrid dataGrid, DataGridCellInfo currentCellInfo)
        {
            int currentRowIndex = dataGrid.Items.IndexOf(currentCellInfo.Item);
            int currentColumnIndex = dataGrid.Columns.IndexOf(currentCellInfo.Column);

            if (currentColumnIndex + 1 < dataGrid.Columns.Count)
            {
                // Move to the next column in the same row
                dataGrid.CurrentCell = new DataGridCellInfo(dataGrid.Items[currentRowIndex], dataGrid.Columns[currentColumnIndex + 1]);
                dataGrid.BeginEdit();
            }
            else if (currentRowIndex + 1 < dataGrid.Items.Count)
            {
                // Move to the first column of the next row
                dataGrid.CurrentCell = new DataGridCellInfo(dataGrid.Items[currentRowIndex + 1], dataGrid.Columns[0]);
                dataGrid.BeginEdit();
            }
        }
        
        private void FocusAndBeginEdit(DataGrid datagrid, DataGridRow row, int columnIndex)
        {
            // Get the row index from the DataGrid's ItemContainerGenerator
            int rowIndex = datagrid.ItemContainerGenerator.IndexFromContainer(row);

            // Ensure the row index is valid
            if (rowIndex < 0 || rowIndex >= datagrid.Items.Count) return;

            DataGridCell cell = GetCell(datagrid, row, columnIndex);
            if (cell != null)
            {
                Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    datagrid.CurrentCell = new DataGridCellInfo(datagrid.Items[rowIndex], datagrid.Columns[columnIndex]);
                    datagrid.SelectedCells.Clear();
                    datagrid.SelectedCells.Add(datagrid.CurrentCell);
                    cell.Focus();
                    Keyboard.Focus(cell);
                    // Optionally, uncomment this line if immediate edit is needed:
                    // datagrid.BeginEdit();
                }), System.Windows.Threading.DispatcherPriority.Input);
            }
        }

        private bool IsChildOf(DependencyObject parent, DependencyObject child)
        {
            if (parent == null || child == null)
                return false;

            DependencyObject currentParent = child;

            // Traverse up the visual tree until we find the parent or hit the root element
            while (currentParent != null)
            {
                if (currentParent == parent)
                    return true;
                currentParent = VisualTreeHelper.GetParent(currentParent);
            }

            return false;
        }

        #endregion

    }
}
using BatoirApp.Model;
using BatoirApp.MVVM.Interfaces;
using DocumentFormat.OpenXml.InkML;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace BatoirApp.MVVM.Services
{
    public class OrderService : IAsyncDataProvider<Order>, IDisposable
    {
        private readonly BatoirDbContext _context;
        public OrderService(BatoirDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }
        public async Task<List<Order>> GetAllAsync()
        {
            try
            {
                return await _context.Orders.Include(o => o.OrderProductLines).Include(o => o.Customer).ToListAsync();
            }
            catch (Exception ex)
            {
                // Handle any exceptions here
                MessageBox.Show("An error occurred while loading oreder: " + ex.Message);
                return new List<Order>(); // Return an empty list or handle the error as needed
            }
        }


        public Task<Order> AddAsync(Order order)
        {
            try
            {
                if (order.Customer != null)
                {
                    // Check if the Customer is already tracked; if not, attach it.
                    var trackedCustomer = _context.Customers.Local
                                           .FirstOrDefault(c => c.CustomerId == order.Customer.CustomerId);

                    // If another instance is already tracked, detach it to avoid conflict
                    if (trackedCustomer != null && trackedCustomer != order.Customer)
                    {
                        _context.Entry(trackedCustomer).State = EntityState.Detached;
                    }

                    // Attach the customer if it's not being tracked
                    if (_context.Entry(order.Customer).State == EntityState.Detached)
                    {
                        _context.Attach(order.Customer);
                    }


                }

                foreach (var orderProductLine in order.OrderProductLines)
                {
                    if (orderProductLine.Product != null)
                    {
                        // Ensure only one instance of Product is tracked
                        var trackedProduct = _context.Products.Local
                                                .FirstOrDefault(p => p.ProductId == orderProductLine.Product.ProductId);
                        if (trackedProduct != null && trackedProduct != orderProductLine.Product)
                        {
                            _context.Entry(trackedProduct).State = EntityState.Detached;
                        }

                        // Attach if it's not already tracked
                        if (_context.Entry(orderProductLine.Product).State == EntityState.Detached)
                        {
                            _context.Attach(orderProductLine.Product);
                        }
                    }

                    // Ensure correct state for each OrderProductLine
                    if (_context.Entry(orderProductLine).State == EntityState.Detached)
                    {
                        _context.Entry(orderProductLine).State = EntityState.Added;
                    }
                    else
                    {
                        _context.Entry(orderProductLine).State = EntityState.Unchanged;
                    }
                }

                _context.Orders.Add(order);
                _context.SaveChanges();


                // Detach customer and products to prevent tracking conflicts on reuse

                _context.Entry(order.Customer).State = EntityState.Detached;
                foreach (var line in order.OrderProductLines)
                {
                    _context.Entry(line.Product).State = EntityState.Detached;
                }

                return Task.FromResult(order); // Wrap in a Task to match the async signature
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while adding the order: " + ex.Message);
                return Task.FromResult<Order>(null);
            }
        }



        #region Old AddAsync
        //public Task<Order> AddAsync(Order item)
        //{
        //    try
        //    {
        //        if (item.Customer != null)
        //            _context.Customers.Attach(item.Customer);

        //        foreach (var orderProductLine in item.OrderProductLines)
        //        {
        //            if (orderProductLine.Product != null)
        //            {
        //                if (_context.Entry(orderProductLine.Product).State == EntityState.Detached)
        //                {
        //                    _context.Products.Attach(orderProductLine.Product);
        //                }
        //            }

        //            if (_context.Entry(orderProductLine).State == EntityState.Detached)
        //            {
        //                _context.Entry(orderProductLine).State = EntityState.Added;
        //            }
        //            else
        //            {
        //                _context.Entry(orderProductLine).State = EntityState.Unchanged;
        //            }
        //        }

        //        _context.Orders.Add(item);
        //        _context.SaveChanges();

        //        // Detach the customer to stop tracking it
        //        if (item.Customer != null)
        //        {
        //            _context.Entry(item.Customer).State = EntityState.Detached;
        //        }

        //        return Task.FromResult(item); // Wrap in a Task to match the async signature
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("An error occurred while adding the order: " + ex.Message);
        //        return Task.FromResult<Order>(null);
        //    }
        //} 
        #endregion



        public Task DeleteAsync(Order item)
        {
            throw new NotImplementedException();
        }

        public Task<bool> ExistsAsync(Order item)
        {
            throw new NotImplementedException();
        }
        public Task<Order> GetTypeByIdAsync(int id)
        {
            throw new NotImplementedException();
        }

        public Task UpdateAsync(Order item)
        {
            throw new NotImplementedException();
        }
        public void Dispose()
        {
            _context.Dispose();
        }

        public async Task<List<Order>> GetAllByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            try
            {
                return await _context.Orders
                    .Include(o => o.OrderProductLines).ThenInclude(opl => opl.Product)
                    .Include(o => o.Customer)
                    .Where(o => o.OrderDate.Date >= startDate.Date && o.OrderDate.Date <= endDate.Date)
                    .ToListAsync();
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while loading orders by date range: " + ex.Message);
                return new List<Order>();
            }
        }

        public async Task<List<Order>> GetFilteredOrdersAsync(
            DateTime? startDate,
            DateTime? endDate,
            Customer customer,
            Product product,
            bool isPaid,
            bool isPartial,
            bool isUnpaid)
        {
            // Start with all orders
            var query = _context.Set<Order>()
                        .Include(o => o.OrderProductLines)
                        .Include(o => o.Customer)
                        .AsQueryable();

            // Apply date range filter if specified
            if (startDate.HasValue)
            {
                query = query.Where(order => order.OrderDate >= startDate.Value);
            }
            if (endDate.HasValue)
            {
                query = query.Where(order => order.OrderDate <= endDate.Value.Date.AddDays(1).AddTicks(-1));
            }

            // Apply customer filter if a customer is specified
            if (customer != null)
            {
                query = query.Where(order => order.Customer != null &&
                                             order.Customer.FirstName == customer.FirstName);
            }
            // Apply product filter if a product is specified
            if (product != null)
            {
                query = query.Where(order => order.OrderProductLines
                                              .Any(opl => opl.ProductId == product.ProductId)); // Filter by product
            }

            var orders = await query.ToListAsync();
            
            // Apply PaymentStatus filter in memory only if at least one of the flags is true
            if (isPaid || isPartial || isUnpaid)
            {
                orders = orders.Where(order =>
                                (isPaid && order.PaymentStatus == "Paid") ||
                                (isPartial && order.PaymentStatus == "Partial") ||
                                (isUnpaid && order.PaymentStatus == "Unpaid"))
                            .ToList();
            }

            return orders;

        }
    }
}
using BatoirApp.Model;
using BatoirApp.MVVM.Interfaces;
using BatoirApp.MVVM.Validators;
using DocumentFormat.OpenXml.InkML;
using FluentValidation.Results;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Windows;

namespace BatoirApp.MVVM.Services
{
    public class CustomerService : IAsyncDataProvider<Customer>, IDisposable
    {

        public CustomerService(BatoirDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }

        private readonly BatoirDbContext _context;
       
        public async Task<List<Customer>> GetAllAsync()
        {
            try
            {
                return await _context.Customers
                .Include(c => c.CustomerPhones)
                .ToListAsync();
            }
            catch (Exception ex)
            {
                // Handle any exceptions here
                MessageBox.Show("An error occurred while loading customers: " + ex.Message);
                return new List<Customer>(); // Return an empty list or handle the error as needed
            }
        }

        public async Task<Customer> AddAsync(Customer customer)
        {
            try
            {
                await Task.Run(() =>
                {
                    _context.Customers.Add(customer);
                    _context.SaveChanges();
                    MessageBox.Show($"Customer: {customer.FirstName} added successfully.");
                });
                return customer;
            }
            catch (Exception ex)
            {
                // Handle any exceptions here
                MessageBox.Show("An error occurred while adding customer: " + ex.Message);
                return null;
            }
        }

        public async Task DeleteAsync(Customer customer)
        {
            try
            {
                var customerToDelete = _context.Customers.Find(customer.CustomerId);
                if (customerToDelete != null)
                {
                    await Task.Run(() =>
                             {
                                 _context.Customers.Remove(customerToDelete);
                                 _context.SaveChangesAsync();
                                 MessageBox.Show($"Customer: {customer.FirstName} deleted successfully.");
                             });
                }
            }
            catch (Exception ex)
            {
                // Handle any exceptions here
                MessageBox.Show("An error occurred while deleting customer: " + ex.Message);
            }
        }



        public async Task UpdateAsync(Customer customer)
        {
            try
            {
                if (customer != null)
                {
                    // Check if another instance with the same key is already being tracked
                    var trackedCustomer = _context.Customers.Local
                                        .FirstOrDefault(c => c.CustomerId == customer.CustomerId);


                    if (trackedCustomer != null && trackedCustomer != customer)
                    {
                        // Detach the tracked instance to avoid conflict
                        _context.Entry(trackedCustomer).State = EntityState.Detached;
                    }

                    // Retrieve the existing customer from the database
                    var existingCustomer = await _context.Customers.FindAsync(customer.CustomerId);

                    if (existingCustomer != null)
                    {
                        // Update properties on the existing customer instance
                        existingCustomer.FirstName = customer.FirstName;
                        existingCustomer.LastName = customer.LastName;
                        existingCustomer.NisNumber = customer.NisNumber;
                        existingCustomer.NifNumber = customer.NifNumber;
                        existingCustomer.ArtNumber = customer.ArtNumber;
                        existingCustomer.Address = customer.Address;
                        existingCustomer.CustomerPhones = customer.CustomerPhones;
                        existingCustomer.ActualSold = customer.ActualSold;

                        await _context.SaveChangesAsync();

                        MessageBox.Show($"Customer: {existingCustomer.FirstName} updated successfully.");
                    }
                    else
                    {
                        MessageBox.Show("Customer not found in the database.");
                    }
                }
                else
                {
                    MessageBox.Show("Invalid customer data.");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while updating customer: " + ex.Message);
            }
        }


        public async Task<Customer> GetTypeByIdAsync(int id)
        {
            try
            {
                var customer = await _context.Customers
                    .FirstOrDefaultAsync(c => c.CustomerId == id);

                return customer;
            }
            catch (Exception ex)
            {
                // Handle any exceptions here
                MessageBox.Show("An error occurred while retrieving customer: " + ex.Message);
                return null; // Return null or handle the error as needed
            }
        }

        // Dispose Dispose Dispose ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        public void Dispose()
        {
            _context.Dispose();
        }

        public async Task<bool> ExistsAsync(Customer customer)
        {
            var phoneNumbers = customer.CustomerPhones
           .Where(cp => !string.IsNullOrEmpty(cp.PhoneNumber))
           .Select(cp => cp.PhoneNumber)
           .ToList();

            bool exists = await _context.Customers
                .AnyAsync(c =>
                    (c.NifNumber != null && c.NifNumber == customer.NifNumber) ||
                    (c.NisNumber != null && c.NisNumber == customer.NisNumber) ||
                    (c.RegisterNumber != null && c.RegisterNumber == customer.RegisterNumber) ||
                    (c.ArtNumber != null && c.ArtNumber == customer.ArtNumber));

            if (exists)
            {
                return true;
            }

            if (phoneNumbers.Any())
            {
                exists = await _context.CustomerPhones
                    .AnyAsync(p => phoneNumbers.Contains(p.PhoneNumber));
            }

            return exists;
            #region Old code working 
            // var phoneNumbers = customer.CustomerPhones
            //.Where(cp => !string.IsNullOrEmpty(cp.PhoneNumber))
            //.Select(cp => cp.PhoneNumber)
            //.ToList();

            // bool exists = await _context.Customers
            //    .AnyAsync(c =>
            //         (c.NifNumber != null && c.NifNumber == customer.NifNumber)
            //         || (c.NisNumber != null && c.NisNumber == customer.NisNumber)
            //         || (c.RegisterNumber != null && c.RegisterNumber == customer.RegisterNumber)
            //         || (c.ArtNumber != null && c.ArtNumber == customer.ArtNumber));

            // if (exists)
            // {
            //     return true;
            // }

            // if (phoneNumbers.Any())
            // {
            //     exists = await _context.CustomerPhones
            //         .AnyAsync(p => !string.IsNullOrEmpty(p.PhoneNumber) && phoneNumbers.Contains(p.PhoneNumber));
            // }

            // return exists;          
            #endregion
        }

        public Task<List<Customer>> GetAllByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            throw new NotImplementedException();
        }


        public Task<List<Customer>> GetFilteredOrdersAsync(DateTime? startDate, DateTime? endDate, Customer customer, Product product, bool isPaid, bool isPartial, bool isUnpaid)
        {
            throw new NotImplementedException();
        }
    }
}using AutoCompleteTextBox.Editors;
using Autofac;
using BatoirApp.Model;
using BatoirApp.MVVM.Commands;
using BatoirApp.MVVM.Interfaces;
using BatoirApp.MVVM.Services;
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;

namespace BatoirApp.ViewModel.Orders
{
    public class EditOrderWindowViewModel : MVVM.Core.ViewModel, IComboSuggestionProvider
    {
        public decimal OrderTotal => OrderProductLines.Sum(line => line.SubTotal);
       
        private bool _isProductSearch;

        private bool _isCustomerSearch;
        public bool IsProductSearch
        {
            get { return _isProductSearch; }
            set
            {
                _isProductSearch = value;
                OnPropertyChanged(nameof(IsProductSearch));
            }
        }

        public bool IsCustomerSearch
        {
            get { return _isCustomerSearch; }
            set
            {
                _isCustomerSearch = value;
                OnPropertyChanged(nameof(IsCustomerSearch));
            }
        }
        private ObservableCollection<Customer> _availableCustomers;
        public ObservableCollection<Customer> AvailableCustomers
        {
            get { return _availableCustomers; }
            set
            {
                _availableCustomers = value;
                OnPropertyChanged();
            }
        }

        private ObservableCollection<Product> _availableProducts;
        public ObservableCollection<Product> AvailableProducts
        {
            get { return _availableProducts; }
            set
            {
                _availableProducts = value;
                OnPropertyChanged();
            }
        }

        private decimal _paymentAmount;

        public decimal PaymentAmount
        {
            get { return _paymentAmount; }
            set 
            {
                _paymentAmount = value;
                OnPropertyChanged();
            }
        }


        private Order _selectedOrder;
        public Order SelectedOrder
        {
            get { return _selectedOrder; }
            set
            {
                _selectedOrder = value;
                OnPropertyChanged(); // Notify when SelectedOrder is updated
            }
        }

        private Product _selectedProduct;
        public Product SelectedProduct
        {
            get { return _selectedProduct; }
            set
            {
                _selectedProduct = value;
                OnPropertyChanged($"{nameof(SelectedProduct)}");
                //ValidateProductName(_product.ProductName);
                //OnPropertyChanged(nameof(IsValidateOrderEnabled));
            }
        }


        public ObservableCollection<OrderProductLine> OrderProductLines { get; set; } 


        public ICommand SaveCommand { get; private set; }
        public ICommand CancelCommand { get; private set; }

        public EditOrderWindowViewModel(Order order, ObservableCollection<Customer> availableCustomers, ObservableCollection<Product> availableProducts)
        {
            AvailableCustomers = availableCustomers;
            AvailableProducts = availableProducts;
            SelectedOrder = order; // Set the order to edit
            OrderProductLines = new ObservableCollection<OrderProductLine>(SelectedOrder.OrderProductLines);
            OrderProductLines.CollectionChanged += OrderProductLines_CollectionChanged;
            SaveCommand = new RelayCommandSimple(SaveOrder);
            CancelCommand = new RelayCommandSimple(CloseWindow);
            foreach (var line in OrderProductLines)
            {
                line.PropertyChanged += OrderProductLine_PropertyChanged;
            }
            SelectedOrder.PaymentAmount = PaymentAmount;
        }

        private void OrderProductLines_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (OrderProductLine line in e.NewItems)
                {
                    line.PropertyChanged += OrderProductLine_PropertyChanged;
                }
            }

            if (e.OldItems != null)
            {
                if (e.NewItems != null)
                {

                    foreach (OrderProductLine line in e.OldItems)
                    {
                        OrderProductLines.Remove(line);
                        line.PropertyChanged -= OrderProductLine_PropertyChanged;
                    }
                }
            }


            OnPropertyChanged(nameof(OrderTotal));
        }

        private void OrderProductLine_PropertyChanged(object? sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(OrderProductLine.SubTotal))
            {
                OnPropertyChanged(nameof(OrderTotal));
            }
        }

        public decimal OrderRemainingAmount => SelectedOrder != null
            ? SelectedOrder.TotalAmount - SelectedOrder.PaymentAmount
            : 0;

        private void SaveOrder(object obj)
        {
            // Logic to save the order changes
        }

        private void CloseWindow(object obj)
        {
            // Logic to close the window
        }

        public IEnumerable GetSuggestions(string filter)
        {
            if (string.IsNullOrWhiteSpace(filter)) return null;
            else if (IsCustomerSearch) return AvailableCustomers.Where(x => x.FirstName.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) > -1).ToArray();
            else if (IsProductSearch) return AvailableProducts.Where(product => product.ProductName.IndexOf(filter, StringComparison.CurrentCultureIgnoreCase) > -1).ToArray();
            return null;
        }

        public IEnumerable GetFullCollection()
        {
            if (IsCustomerSearch) return AvailableCustomers;
            else if (IsProductSearch) return AvailableProducts;
            return null;
        }

        private readonly ICustomerCacheService _customerCacheService;
        
    }
}
using BatoirApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BatoirApp.ViewModel.Orders
{
    public class OrderPaymentPopupWindowViewModel : MVVM.Core.ViewModel
    {
        private string _selectedPaymentMethod;
        public string SelectedPaymentMethod
        {
            get => _selectedPaymentMethod;
            set
            {
                _selectedPaymentMethod = value;
                OnPropertyChanged(nameof(SelectedPaymentMethod));
            }
        }


        private Customer _selectedCustomer;
        public Customer SelectedCustomer
        {
            get { return _selectedCustomer; }
            set
            {
                _selectedCustomer = value;
                OnPropertyChanged(nameof(SelectedCustomer));
            }
        }

        private decimal _PaymentAmount;

        public decimal PaymentAmount
        {
            get => _PaymentAmount;
            set
            {
                _PaymentAmount = value;
                OnPropertyChanged(nameof(PaymentAmount));
                OnPropertyChanged(nameof(OrderRemainingAmount));
                OnPropertyChanged(nameof(CustomerNewBalance));
            }
        }

     

        public decimal orderTotal;
        public decimal OrderTotal { get => orderTotal; set => orderTotal = value; }

        public decimal OrderRemainingAmount => orderTotal - PaymentAmount;
        public decimal CustomerNewBalance => OrderRemainingAmount + SelectedCustomer.ActualSold;


        public OrderPaymentPopupWindowViewModel(Customer selectedCustomer, decimal orderAmount)
        {
            SelectedCustomer = selectedCustomer;
            OrderTotal = orderAmount;
        }


    }
}
#region using
using AutoCompleteTextBox.Editors;
using Autofac;
using BatoirApp.Model;
using BatoirApp.MVVM.Commands;
using BatoirApp.MVVM.Core;
using BatoirApp.MVVM.Interfaces;
using BatoirApp.MVVM.Services;
using BatoirApp.View.Orders;
using BatoirApp.View.Payments;
using BatoirApp.ViewModel.Customers;
using BatoirApp.ViewModel.Payments;
using BatoirApp.ViewModel.Products;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
#endregion

namespace BatoirApp.ViewModel.Orders
{
    public class NewOrderUserControlViewModel : MVVM.Core.ViewModel, IComboSuggestionProvider
    {
        #region Fields
        private readonly IAsyncDataProvider<Order> _orderService;
        private readonly ProductsListViewModel _productsListViewModel;
        private readonly INavigationService _navigationService;
        private readonly IProductCacheService _productCacheService;
        private readonly ICustomerCacheService _customerCacheService;

        private ObservableCollection<Product> _availableProducts;
        private ObservableCollection<Customer> _availableCustomers;
        private Product _selectedProduct;
        private Customer _selectedCustomer;
        private bool _isProductSearch;
        private bool _isCustomerSearch;
        private string _selectedPaymentMethod;
        private Worker _selectedWorker;
        private decimal _newSolde;
        private int _quantity;
        #endregion

        #region Constructor
        public NewOrderUserControlViewModel(IAsyncDataProvider<Order> orderService, ProductsListViewModel productsListViewModel, INavigationService navigationService, IProductCacheService productCacheService, ICustomerCacheService customerCacheService)
        {
            _orderService = orderService;
            _productsListViewModel = productsListViewModel;
            _navigationService = navigationService;
            _productCacheService = productCacheService;
            _customerCacheService = customerCacheService;

            OrderProductLines.CollectionChanged += OrderProductLines_CollectionChanged;
            CreateOrderCommand = new RelayCommandParams(param => CreateOrder(param as OrderPaymentPopupWindowViewModel));
            OpenOrderPaymentPopupWindowCommand = new RelayCommand(OpenOrderPaymentPopupWindow, CanCreateOrder);

            LoadProductsAsync();
            LoadCustomersAsync();
        }
        #endregion

        #region Properties
        public ObservableCollection<Product> AvailableProducts
        {
            get => _availableProducts;
            set { _availableProducts = value; OnPropertyChanged(); }
        }

        public ObservableCollection<Customer> AvailableCustomers
        {
            get => _availableCustomers;
            set { _availableCustomers = value; OnPropertyChanged(); }
        }

        public ObservableCollection<OrderProductLine> OrderProductLines { get; } = new ObservableCollection<OrderProductLine>();

        public ObservableCollection<Worker> Workers { get; set; } = new ObservableCollection<Worker>();
        public ObservableCollection<string> PaymentMethods { get; set; } = new ObservableCollection<string> { "Cash", "Credit Card", "Bank Transfer" };

        public decimal OrderTotal => OrderProductLines.Sum(line => line.SubTotal);
        public decimal? TotalGeneral => OrderTotal + (SelectedCustomer?.ActualSold ?? 0);

        public int Quantity
        {
            get => _quantity;
            set { _quantity = value; OnPropertyChanged(nameof(Quantity)); }
        }

        public string SelectedPaymentMethod
        {
            get => _selectedPaymentMethod;
            set { _selectedPaymentMethod = value; OnPropertyChanged(nameof(SelectedPaymentMethod)); }
        }

        public Worker SelectedWorker
        {
            get => _selectedWorker;
            set { _selectedWorker = value; OnPropertyChanged(nameof(SelectedWorker)); }
        }

        public Customer SelectedCustomer
        {
            get => _selectedCustomer;
            set
            {
                _selectedCustomer = value;
                OnPropertyChanged(nameof(SelectedCustomer));
                OnPropertyChanged(nameof(IsValidateOrderEnabled));
            }
        }

        public Product SelectedProduct
        {
            get => _selectedProduct;
            set
            {
                _selectedProduct = value;
                OnPropertyChanged(nameof(SelectedProduct));
                OnPropertyChanged(nameof(IsValidateOrderEnabled));
            }
        }

        public decimal NewSolde
        {
            get => _newSolde;
            set { _newSolde = value; OnPropertyChanged(nameof(NewSolde)); }
        }

        public bool IsValidateOrderEnabled => SelectedCustomer != null && OrderProductLines.Any();

        public bool IsProductSearch
        {
            get => _isProductSearch;
            set { _isProductSearch = value; OnPropertyChanged(nameof(IsProductSearch)); }
        }

        public bool IsCustomerSearch
        {
            get => _isCustomerSearch;
            set { _isCustomerSearch = value; OnPropertyChanged(nameof(IsCustomerSearch)); }
        }

        public List<string> ProductSuggestions => AvailableProducts.Select(p => p.ProductName).ToList();
        #endregion

        #region Commands
        public ICommand B { get; set; }
        public ICommand AddOrderLineCommand { get; }
        public RelayCommand NavigateToHomeCommand { get; set; }
        public RelayCommandParams CreateOrderCommand { get; set; }
        public RelayCommand OpenOrderPaymentPopupWindowCommand { get; }
        #endregion

        #region Methods

        private void OpenOrderPaymentPopupWindow(object obj)
        {
            var popupWindow = new OrderPaymentPopupWindowView();
            var popupWindowViewModel = new OrderPaymentPopupWindowViewModel(SelectedCustomer, OrderTotal);
            popupWindow.DataContext = popupWindowViewModel;

            if (popupWindow.ShowDialog() == true)
                CreateOrder(popupWindowViewModel);
        }

        private bool CanCreateOrder(object obj) => true;

        private async void CreateOrder(OrderPaymentPopupWindowViewModel popupWindowViewModel)
        {
            var newOrder = new Order
            {
                Customer = SelectedCustomer,
                OrderDate = DateTime.Now,
                OrderProductLines = new List<OrderProductLine>(OrderProductLines),
                PaymentAmount = popupWindowViewModel.PaymentAmount,
                TotalAmount = popupWindowViewModel.orderTotal,
                OrderNotes = string.Empty,
                NewSolde = popupWindowViewModel.CustomerNewBalance,
            };

            if (SelectedCustomer != null)
            {
                SelectedCustomer.ActualSold = newOrder.NewSolde;
                
            }
            try
            {
                await _orderService.AddAsync(newOrder);

                // Separate customer update logic
                await _customerCacheService.UpdateAsync(SelectedCustomer);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error Adding new order: {ex.Message}");
            }
        }

        private async void LoadProductsAsync()
        {
            try
            {
                var products = await _productCacheService.GetAllAsync();
                AvailableProducts = new ObservableCollection<Product>(products);
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while loading products: " + ex.Message);
            }
        }

        private async void LoadCustomersAsync()
        {
            try
            {
                var customers = await _customerCacheService.GetAllAsync();
                AvailableCustomers = new ObservableCollection<Customer>(customers);
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while loading customers: " + ex.Message);
            }
        }

        private void OrderProductLines_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (OrderProductLine line in e.NewItems)
                    line.PropertyChanged += OrderProductLine_PropertyChanged;
            }

            if (e.OldItems != null)
            {
                foreach (OrderProductLine line in e.OldItems)
                    line.PropertyChanged -= OrderProductLine_PropertyChanged;
            }

            OnPropertyChanged(nameof(OrderTotal));
            OnPropertyChanged(nameof(IsValidateOrderEnabled));
        }

        private void OrderProductLine_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(OrderProductLine.SubTotal))
            {
                OnPropertyChanged(nameof(OrderTotal));
                OnPropertyChanged(nameof(TotalGeneral));
                OnPropertyChanged(nameof(IsValidateOrderEnabled));
            }
        }

        public IEnumerable GetSuggestions(string filter)
        {
            if (string.IsNullOrWhiteSpace(filter)) return null;
            return IsCustomerSearch ? AvailableCustomers.Where(x => x.FirstName.Contains(filter, StringComparison.InvariantCultureIgnoreCase)).ToArray()
                                    : IsProductSearch ? AvailableProducts.Where(product => product.ProductName.Contains(filter, StringComparison.CurrentCultureIgnoreCase)).ToArray()
                                    : null;
        }

        public IEnumerable GetFullCollection() => IsCustomerSearch ? AvailableCustomers : IsProductSearch ? AvailableProducts : null;

        public void ValidateProductName(string input)
        {
            if (!ProductSuggestions.Contains(input))
                SelectedProduct = null;
        }

        #endregion
    }
}



#region OLD code
//#region using
//using AutoCompleteTextBox.Editors;
//using Autofac;
//using BatoirApp.Model;
//using BatoirApp.MVVM.Commands;
//using BatoirApp.MVVM.Core;
//using BatoirApp.MVVM.Interfaces;
//using BatoirApp.MVVM.Services;
//using BatoirApp.View.Orders;
//using BatoirApp.View.Payments;
//using BatoirApp.ViewModel.Customers;
//using BatoirApp.ViewModel.Payments;
//using BatoirApp.ViewModel.Products;
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Collections.ObjectModel;
//using System.ComponentModel;
//using System.Linq;
//using System.Windows;
//using System.Windows.Input;
//#endregion

//namespace BatoirApp.ViewModel.Orders
//{
//    public class NewOrderUserControlViewModel : MVVM.Core.ViewModel, IComboSuggestionProvider
//    {
//        #region Ctor
//        public NewOrderUserControlViewModel(IAsyncDataProvider<Order> orderService, ProductsListViewModel productsListViewModel, INavigationService navigationService, IProductCacheService productCacheService, ICustomerCacheService customerCacheService)
//        {
//            _orderService = orderService;
//            _productsListViewModel = productsListViewModel;
//            OrderProductLines.CollectionChanged += OrderProductLines_CollectionChanged;
//            _navigationService = navigationService;
//            _productCacheService = productCacheService;
//            _customerCacheService = customerCacheService;
//            CreateOrderCommand = new RelayCommandParams(param => CreateOrder(param as OrderPaymentPopupWindowViewModel));
//            OpenOrderPaymentPopupWindowCommand = new RelayCommand(OpenOrderPaymentPopupWindow, CanCreateOrder);
//            LoadProductsAsync();
//            LoadCustomersAsync();
//        }

//        private void OpenOrderPaymentPopupWindow(object obj)
//        {
//            var popupWindow = new OrderPaymentPopupWindowView();
//            var popupWindowViewModel = new OrderPaymentPopupWindowViewModel(SelectedCustomer, OrderTotal);
//            // Set the DataContext for the popup window
//            popupWindow.DataContext = popupWindowViewModel;

//            // Show the popup window as a dialog
//            if (popupWindow.ShowDialog() == true) // Check if the dialog was confirmed
//            {
//                CreateOrder(popupWindowViewModel); // Call CreateOrder with the view model

//            }
//        }

//        #endregion

//        #region PaymentPopup related 

//        public ObservableCollection<Worker> Workers { get; set; } = new ObservableCollection<Worker>
//        {
//            // Populate this list with available workers 

//        };

//        public ObservableCollection<string> PaymentMethods { get; set; } = new ObservableCollection<string>
//        {
//            "Cash", "Credit Card", "Bank Transfer"
//        };

//        private decimal _newSolde;
//        public decimal NewSolde
//        {
//            get => _newSolde;
//            set
//            {
//                _newSolde = value;
//                OnPropertyChanged(nameof(NewSolde));
//            }
//        }


//        private string _selectedPaymentMethod;
//        public string SelectedPaymentMethod
//        {
//            get => _selectedPaymentMethod;
//            set
//            {
//                _selectedPaymentMethod = value;
//                OnPropertyChanged(nameof(SelectedPaymentMethod));
//            }
//        }

//        private Worker _selectedWorker;
//        public Worker SelectedWorker
//        {
//            get => _selectedWorker;
//            set
//            {
//                _selectedWorker = value;
//                OnPropertyChanged(nameof(SelectedWorker));
//            }
//        }
//        #endregion

//        #region NewOrderUserContol related

//        public List<string> _productSuggestions => AvailableProducts.Select(p => p.ProductName).ToList();

//        private ObservableCollection<Customer> customers;

//        public ObservableCollection<Product> AvailableProducts
//        {
//            get { return _availableProducts; }
//            set
//            {
//                _availableProducts = value;
//                OnPropertyChanged();
//            }
//        }

//        public ObservableCollection<Customer> AvailableCustomers
//        {
//            get { return _availableCustomers; }
//            set
//            {
//                _availableCustomers = value;
//                OnPropertyChanged();
//            }
//        }

//        public ObservableCollection<OrderProductLine> OrderProductLines { get; set; } = new ObservableCollection<OrderProductLine>();

//        private int _quantity;
//        public int Quantity
//        {
//            get => _quantity;
//            set
//            {
//                _quantity = value;
//                OnPropertyChanged(nameof(Quantity));
//            }
//        }

//        public Product SelectedProduct
//        {
//            get { return _selectedProduct; }
//            set
//            {
//                _selectedProduct = value;
//                OnPropertyChanged($"{nameof(SelectedProduct)}");
//                //ValidateProductName(_product.ProductName);
//                OnPropertyChanged(nameof(IsValidateOrderEnabled));
//            }
//        }

//        public decimal? TotalGeneral => OrderTotal + (SelectedCustomer?.ActualSold ?? 0);

//        public decimal OrderTotal => OrderProductLines.Sum(line => line.SubTotal);
//        private Customer _selectedCustomer;
//        public Customer SelectedCustomer
//        {
//            get { return _selectedCustomer; }
//            set
//            {
//                _selectedCustomer = value;
//                OnPropertyChanged(nameof(SelectedCustomer));
//                OnPropertyChanged(nameof(IsValidateOrderEnabled));
//            }
//        }

//        private ObservableCollection<Product> _availableProducts;

//        private ObservableCollection<Customer> _availableCustomers;

//        private Product _selectedProduct;

//        #endregion

//        #region Services
//        private readonly IProductCacheService _productCacheService;
//        private readonly ICustomerCacheService _customerCacheService;
//        private IAsyncDataProvider<Order> _orderService;
//        private readonly INavigationService _navigationService;
//        #endregion

//        #region View models passed to class
//        private readonly ProductsListViewModel _productsListViewModel;

//        private readonly CustomersListViewModel _customersListViewModel;
//        #endregion

//        #region Bools 
//        public bool IsValidateOrderEnabled => SelectedCustomer != null && OrderProductLines.Any();

//        private bool _isProductSearch;

//        private bool _isCustomerSearch;

//        public bool IsProductSearch
//        {
//            get { return _isProductSearch; }
//            set
//            {
//                _isProductSearch = value;
//                OnPropertyChanged(nameof(IsProductSearch));
//            }
//        }

//        public bool IsCustomerSearch
//        {
//            get { return _isCustomerSearch; }
//            set
//            {
//                _isCustomerSearch = value;
//                OnPropertyChanged(nameof(IsCustomerSearch));
//            }
//        }

//        #endregion

//        #region Commands

//        public ICommand B { get; set; }
//        public ICommand AddOrderLineCommand { get; }
//        public MVVM.Core.RelayCommand NavigateToHomeCommand { get; set; }
//        public RelayCommandParams CreateOrderCommand { get; set; }
//        public RelayCommand OpenOrderPaymentPopupWindowCommand { get; }

//        #endregion

//        #region Methods


//        private bool CanCreateOrder(object obj)
//        {
//            return true;
//            //return IsValidateOrderEnabled;
//        }



//        private void CreateOrder(OrderPaymentPopupWindowViewModel popupWindowViewModel)
//        {
//            var newOrder = new Order
//            {
//                Customer = SelectedCustomer,
//                OrderDate = DateTime.Now,
//                OrderProductLines = new List<OrderProductLine>(this.OrderProductLines),
//                PaymentAmount = popupWindowViewModel.PaymentAmount,
//                TotalAmount = popupWindowViewModel.orderTotal,
//                OrderNotes = string.Empty,
//                NewSolde = popupWindowViewModel.CustomerNewBalance,
//                //NewSolde = (SelectedCustomer?.ActualSold ?? 0) + OrderTotal - PaymentAmount

//            };

//            if (SelectedCustomer != null)
//            {
//                SelectedCustomer.ActualSold = newOrder.NewSolde;
//                _customerCacheService.UpdateAsync(SelectedCustomer);
//            }
//            try
//            {
//                _orderService.AddAsync(newOrder);
//            }
//            catch (Exception ex)
//            {
//                MessageBox.Show($"Error Adding new order: {ex.Message}");
//            }

//        }
//        private async void LoadProductsAsync()
//        {

//            try
//            {
//                var products = await _productCacheService.GetAllAsync();
//                AvailableProducts = new ObservableCollection<Product>(products);
//            }
//            catch (Exception ex)
//            {
//                // Handle exceptions appropriately (logging, user notification, etc.)
//                MessageBox.Show("An error occurred while loading products: " + ex.Message);
//            }

//        }

//        private async void LoadCustomersAsync()
//        {

//            try
//            {
//                var customers = await _customerCacheService.GetAllAsync();
//                AvailableCustomers = new ObservableCollection<Customer>(customers);
//            }
//            catch (Exception ex)
//            {
//                // Handle exceptions appropriately (logging, user notification, etc.)
//                MessageBox.Show("An error occurred while loading customers: " + ex.Message);
//            }

//        }

//        private void OrderProductLines_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
//        {
//            if (e.NewItems != null)
//            {
//                foreach (OrderProductLine line in e.NewItems)
//                {
//                    line.PropertyChanged += OrderProductLine_PropertyChanged;
//                    var cus = SelectedCustomer;
//                }
//            }

//            if (e.OldItems != null)
//            {
//                if (e.NewItems != null)
//                {

//                    foreach (OrderProductLine line in e.OldItems)
//                    {
//                        OrderProductLines.Remove(line);
//                        line.PropertyChanged -= OrderProductLine_PropertyChanged;
//                    }
//                }
//            }


//            OnPropertyChanged(nameof(OrderTotal));
//            OnPropertyChanged(nameof(IsValidateOrderEnabled));
//        }

//        private void OrderProductLine_PropertyChanged(object sender, PropertyChangedEventArgs e)
//        {
//            if (e.PropertyName == nameof(OrderProductLine.SubTotal))
//            {
//                OnPropertyChanged(nameof(OrderTotal));
//                OnPropertyChanged(nameof(TotalGeneral));
//                OnPropertyChanged(nameof(IsValidateOrderEnabled));
//            }
//        }

//        public IEnumerable GetSuggestions(string filter)
//        {
//            if (string.IsNullOrWhiteSpace(filter)) return null;
//            else if (IsCustomerSearch) return AvailableCustomers.Where(x => x.FirstName.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) > -1).ToArray();
//            else if (IsProductSearch) return AvailableProducts.Where(product => product.ProductName.IndexOf(filter, StringComparison.CurrentCultureIgnoreCase) > -1).ToArray();
//            return null;
//        }

//        public IEnumerable GetFullCollection()
//        {
//            if (IsCustomerSearch) return AvailableCustomers;
//            else if (IsProductSearch) return AvailableProducts;
//            return null;
//        }

//        public void ValidateProductName(string input)
//        {
//            if (!_productSuggestions.Contains(input))
//            {
//                SelectedProduct = null; // or handle as needed
//            }
//        }




//        #endregion
//    }

//}


#endregion

<Window x:Class="BatoirApp.View.Orders.OrderPaymentPopupWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BatoirApp.View.Orders"
        xmlns:viewModel="clr-namespace:BatoirApp.ViewModel.Orders"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance Type=viewModel:OrderPaymentPopupWindowViewModel}"
        Title="OrderPaymentPopupWindowView"
        Height="450"
        Width="800">
    <Grid>
        <StackPanel Margin="20">

            <!--#region Payment Title -->
            <TextBlock FontSize="36"
                       FontWeight="Bold"
                       Text="Payment Details"
                       Margin="0,0,0,40"
                       HorizontalAlignment="Center" />
            <!--#endregion-->

            <!--#region Order amount -->
            <Grid Margin="0,10">
                <TextBlock Text="Order Amount:" />
                <TextBlock Background="AliceBlue"
                           x:Name="TotalAmountTextBox"
                           Text="{Binding OrderTotal}"
                           Width="200" />
            </Grid>
            <!--#endregion-->

            <!--#region Payment Amount -->
            <Grid Margin="0,10">
                <TextBlock Text="Payment Amount:" />
                <TextBox x:Name="PaymentAmountTextBox"
                         Width="200"
                         Background="AliceBlue"
                         Text="{Binding PaymentAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            </Grid>
            <!--#endregion-->

            <!--#region Order amount -->
            <Grid Margin="0,10">
                <TextBlock Text="Order Remaining Amount:" />
                <TextBlock Background="AliceBlue"
                           x:Name="OrderRemainingAmount"
                           Text="{Binding OrderRemainingAmount}"
                           Width="200" />
            </Grid>
            <!--#endregion-->

            <Separator/>
            <Grid Margin="0,10">
                <TextBlock Text="Customer previous sold:" />
                <TextBlock x:Name="SelectedCustomerOldSold"
                           Text="{Binding SelectedCustomer.ActualSold}"
                           Width="200"
                           Background="AliceBlue" />
            </Grid>





            <!--#region New Solde -->
            <Grid Margin="0,10">
                <TextBlock Text="Customer New Balance:" />
                <TextBlock x:Name="NewSoldeTextBox"
                           Text="{Binding CustomerNewBalance }"
                           Width="200"
                           Background="AliceBlue" />
            </Grid>
            <!--#endregion-->

            <!--#region Confirmation buttons -->
            <StackPanel Orientation="Horizontal"
                        HorizontalAlignment="Center">
                
                <Button Content="Confirm"
                        Click="OnConfirmButtonClick"
                        Width="100"
                        Margin="0,10,0,0" />

                <Button Content="Cancel"
                        Width="100"
                        Click="OnCancelButtonClick"
                        Margin="0,10,0,0" />

            </StackPanel>
            <!--#endregion-->

        </StackPanel>
    </Grid>
</Window>
why when create an order for the first time i got no error and when i recreate a nother order for the same previos customer i got :  The instance of entity type 'Customer' cannot be tracked because another instance with the same key value for {'CustomerId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.