using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;

using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;

namespace FasdDesktopUi.Basics.UserControls
{
    /// <summary>
    /// Interaction logic for HoldTicketDialog.xaml
    /// </summary>
    public partial class HoldTicketDialog : UserControl, INotifyPropertyChanged
    {
        #region DataProvider

        public cSupportCaseDataProvider DataProvider
        {
            get { return (cSupportCaseDataProvider)GetValue(DataProviderProperty); }
            set
            {
                SetValue(DataProviderProperty, value);
            }
        }

        public static readonly DependencyProperty DataProviderProperty =
            DependencyProperty.Register("DataProvider", typeof(cSupportCaseDataProvider), typeof(HoldTicketDialog), new PropertyMetadata(null, DataProviderChanged));

        private static void DataProviderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is HoldTicketDialog me))
                return;
            //me.UpdateReasonsComboBoxAsync();
        }

        #endregion


        public event EventHandler CommentChanged;



        public string Comment
        {
            get { return (string)GetValue(CommentProperty); }
            set { SetValue(CommentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Comment.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommentProperty =
            DependencyProperty.Register("Comment", typeof(string), typeof(HoldTicketDialog), new PropertyMetadata(string.Empty, OnCommentChanged));

        private static void OnCommentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (HoldTicketDialog)d;
            control.CommentChanged?.Invoke(control, EventArgs.Empty);
        }

        public event EventHandler SelectedReminderDateChanged;

        public DateTime SelectedReminderDate
        {
            get { return (DateTime)GetValue(SelectedReminderDateProperty); }
            set { SetValue(SelectedReminderDateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedReminderDate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedReminderDateProperty =
            DependencyProperty.Register("SelectedReminderDate", typeof(DateTime), typeof(HoldTicketDialog), new PropertyMetadata(DateTime.MinValue, OnSelectedReminderDateChanged));

        private static void OnSelectedReminderDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (HoldTicketDialog)d;
            control.SelectedReminderDateChanged?.Invoke(control, EventArgs.Empty);
        }

        private int _selectedHour;
        public int SelectedHour
        {
            get { return _selectedHour; }
            set
            {
                if (_selectedHour != value)
                {
                    _selectedHour = value;
                    OnPropertyChanged(nameof(SelectedHour));
                    setReminderDate();
                }
            }
        }
        private int _selectedMinute;
        public int SelectedMinute
        {
            get { return _selectedMinute; }
            set
            {
                if (_selectedMinute != value)
                {
                    _selectedMinute = value;
                    OnPropertyChanged(nameof(SelectedMinute));
                    setReminderDate();
                }
            }
        }

        private DateTime _selectedDate;
        public DateTime SelectedDate
        {
            get { return _selectedDate; }
            set
            {
                if (_selectedDate != value)
                {
                    _selectedDate = value;
                    OnPropertyChanged(nameof(SelectedDate));
                    setReminderDate();
                }
            }
        }

        public ObservableCollection<int> HoursRange { get; set; }
        public ObservableCollection<int> MinutesRange { get; set; }


        public HoldTicketDialog(cSupportCaseDataProvider cDataProviderBase)
        {

            DataProvider = cDataProviderBase;
            InitializeComponent();
            HoursRange = new ObservableCollection<int>(Enumerable.Range(0, 24).ToList());
            MinutesRange = new ObservableCollection<int>(Enumerable.Range(0, 60).ToList());

            this.DataContext = this;
            SelectedReminderDateDatePicker.DisplayDateStart = DateTime.Now;
            SelectedDate = DateTime.Now.AddDays(1).Date;
            SelectedHour = DateTime.Now.Hour;
            SelectedMinute = DateTime.Now.Minute;
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            UpdateReasonsComboBox();
        }
        private void setReminderDate()
        {

            SelectedReminderDate = new DateTime(
            SelectedDate.Year,
            SelectedDate.Month,
            SelectedDate.Day,
            SelectedHour,
            SelectedMinute,
            0);
        }
        private void UpdateReasonsComboBox()
        {
            try
            {
                if (DataProvider == null) return;

                var resTable = DataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName("M42Wpm-Pickup-ObjectStateReason", false);
                if (resTable == null) return;

                if (!resTable.Columns.TryGetValue("name", out var namesColumn) ||
                    !resTable.Columns.TryGetValue("position", out var positionsColumn) ||
                    !resTable.Columns.TryGetValue("hidden", out var hiddensColumn) ||
                    !resTable.Columns.TryGetValue("state", out var statesColumn) ||
                    !resTable.Columns.TryGetValue("stategroup", out var stateGroupsColumn) ||
                    !resTable.Columns.TryGetValue("id", out var idsColumn)) return;

                var resList = new List<Dictionary<string, object>>();

                for (int i = 0; i < idsColumn.Values.Count; i++)
                {
                    if (statesColumn.Values[i] == null || stateGroupsColumn.Values[i] == null) continue;
                    int? positionValue = null; // Nullabel int für den Fall, dass die Position null ist
                    int stateValue, stateGroupValue;

                    // Überprüft, ob positionsColumn.Values[i] null ist
                    if (positionsColumn.Values[i] != null && int.TryParse(positionsColumn.Values[i].ToString(), out int posVal))
                    {
                        positionValue = posVal;
                    }

                    if (int.TryParse(statesColumn.Values[i].ToString(), out stateValue) && int.TryParse(stateGroupsColumn.Values[i].ToString(), out stateGroupValue))
                    {
                        var eintrag = new Dictionary<string, object>
        {
            { "ID", idsColumn.Values[i] },
            { "DisplayName", namesColumn.Values[i] },
            { "Hidden", Convert.ToBoolean(hiddensColumn.Values[i])},
            { "State", stateValue },
            { "StateGroup", stateGroupValue },
            { "Position", positionValue ?? Int32.MaxValue } // Verwende Int32.MaxValue für null Positionen
        };
                        resList.Add(eintrag);
                    }
                }

                // Filtern und Sortieren, wobei Einträge ohne Position zuletzt erscheinen
                resList = resList.Where(eintrag => !(bool)eintrag["Hidden"] && (int)eintrag["State"] == 203 && (int)eintrag["StateGroup"] == 7)
                                 .OrderBy(eintrag => eintrag["Position"] != null)
                                 .ThenBy(eintrag => (int)eintrag["Position"])
                                 .ToList();

                var targetComboBox = ReasonSelection;
                targetComboBox.Items.Clear();

                foreach (var listValue in resList)
                {
                    targetComboBox.Items.Add(new ComboBoxItem { Content = listValue["DisplayName"], Tag = listValue["ID"] });
                }
            }
            catch (Exception e)
            {
                LogException(e);
            }
        }

        private void DropDownOpened(object sender, EventArgs e)
        {
            try
            {
                if (!(sender is FrameworkElement senderElement))
                    return;

                var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
                cFocusInvoker.InvokeGotFocus(parentBorder, e);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void DropDownClosed(object sender, EventArgs e)
        {
            try
            {
                if (!(sender is FrameworkElement senderElement))
                    return;

                var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
                cFocusInvoker.InvokeLostFocus(parentBorder, e);

                _ = Dispatcher.BeginInvoke((Action)(() =>
                {
                    try
                    {
                        var parentScrollViewer = cUiElementHelper.GetFirstParentOfType<ScrollViewer>(this);
                        Keyboard.ClearFocus();

                        if (parentScrollViewer != null)
                        {
                            parentScrollViewer.Focus();
                            Keyboard.Focus(parentScrollViewer);
                        }
                    }
                    catch (Exception exception)
                    {
                        LogException(exception);
                    }
                }), System.Windows.Threading.DispatcherPriority.Input);
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}
