using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace XplorePlane.Models
{
    // ── Navigation Tree Models ────────────────────────────────────────
    public class NavGroupNode : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _name;
        public string Name
        {
            get => _name;
            set { _name = value; OnPropertyChanged(); }
        }

        private ObservableCollection<object> _children;
        public ObservableCollection<object> Children
        {
            get => _children;
            set { _children = value; OnPropertyChanged(); }
        }

        public NavGroupNode(string name)
        {
            Name = name;
            Children = new ObservableCollection<object>();
        }

        protected void OnPropertyChanged([CallerMemberName] string name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    public class NavLeafNode : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _name;
        public string Name
        {
            get => _name;
            set { _name = value; OnPropertyChanged(); }
        }

        private string _iconColor;
        public string IconColor
        {
            get => _iconColor;
            set { _iconColor = value; OnPropertyChanged(); }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get => _isSelected;
            set { _isSelected = value; OnPropertyChanged(); }
        }

        public NavLeafNode(string name, string IconColor = "#888888", bool IsSelected = false)
        {
            Name = name;
            this.IconColor = IconColor;
            this.IsSelected = IsSelected;
        }

        protected void OnPropertyChanged([CallerMemberName] string name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    // ── Inspection Callout Models ─────────────────────────────────────
    public class InspectionCalloutVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _featureName;
        public string FeatureName
        {
            get => _featureName;
            set { _featureName = value; OnPropertyChanged(); }
        }

        private double _x;
        public double X
        {
            get => _x;
            set { _x = value; OnPropertyChanged(); }
        }

        private double _y;
        public double Y
        {
            get => _y;
            set { _y = value; OnPropertyChanged(); }
        }

        private ObservableCollection<CalloutRowVM> _rows;
        public ObservableCollection<CalloutRowVM> Rows
        {
            get => _rows;
            set { _rows = value; OnPropertyChanged(); }
        }

        public InspectionCalloutVM(string featureName, double x, double y, CalloutRowVM[] rows)
        {
            FeatureName = featureName;
            X = x;
            Y = y;
            Rows = new ObservableCollection<CalloutRowVM>(rows);
        }

        protected void OnPropertyChanged([CallerMemberName] string name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    public class CalloutRowVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _label;
        public string Label
        {
            get => _label;
            set { _label = value; OnPropertyChanged(); }
        }

        private string _nominal;
        public string Nominal
        {
            get => _nominal;
            set { _nominal = value; OnPropertyChanged(); }
        }

        private string _measured;
        public string Measured
        {
            get => _measured;
            set { _measured = value; OnPropertyChanged(); }
        }

        private string _tolerance;
        public string Tolerance
        {
            get => _tolerance;
            set { _tolerance = value; OnPropertyChanged(); }
        }

        private string _deviation;
        public string Deviation
        {
            get => _deviation;
            set { _deviation = value; OnPropertyChanged(); }
        }

        private bool _isPass;
        public bool IsPass
        {
            get => _isPass;
            set { _isPass = value; OnPropertyChanged(); }
        }

        public CalloutRowVM(string label, string nominal, string measured, string tolerance, string deviation, bool isPass)
        {
            Label = label;
            Nominal = nominal;
            Measured = measured;
            Tolerance = tolerance;
            Deviation = deviation;
            IsPass = isPass;
        }

        protected void OnPropertyChanged([CallerMemberName] string name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    // ── Feature Properties Model ──────────────────────────────────────
    public class FeatureProperties : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _name;
        public string Name
        {
            get => _name;
            set { _name = value; OnPropertyChanged(); }
        }

        private string _datumLabel;
        public string DatumLabel
        {
            get => _datumLabel;
            set { _datumLabel = value; OnPropertyChanged(); }
        }

        private double _x;
        public double X
        {
            get => _x;
            set { _x = value; OnPropertyChanged(); }
        }

        private double _y;
        public double Y
        {
            get => _y;
            set { _y = value; OnPropertyChanged(); }
        }

        private double _z;
        public double Z
        {
            get => _z;
            set { _z = value; OnPropertyChanged(); }
        }

        private double _nrX;
        public double NrX
        {
            get => _nrX;
            set { _nrX = value; OnPropertyChanged(); }
        }

        private double _nrY;
        public double NrY
        {
            get => _nrY;
            set { _nrY = value; OnPropertyChanged(); }
        }

        private double _nrZ;
        public double NrZ
        {
            get => _nrZ;
            set { _nrZ = value; OnPropertyChanged(); }
        }

        private double _height;
        public double Height
        {
            get => _height;
            set { _height = value; OnPropertyChanged(); }
        }

        private double _radius;
        public double Radius
        {
            get => _radius;
            set { _radius = value; OnPropertyChanged(); }
        }

        private double _diameter;
        public double Diameter
        {
            get => _diameter;
            set { _diameter = value; OnPropertyChanged(); }
        }

        protected void OnPropertyChanged([CallerMemberName] string name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    // ── RelayCommand Implementation ───────────────────────────────────
    public class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;

        public void Execute(object parameter) => _execute(parameter);
    }
}
