using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using SmartAquaViewer.Controls;
using SmartAquaViewer.DataAnalysis;
using SmartAquaViewer.Model;

namespace SmartAquaViewer.ViewModel
{
    public class EnergyViewModel : INotifyPropertyChanged
    {
        public GraphControlViewModel GraphControlVM { get; } = new GraphControlViewModel();
        public ObservableCollection<GraphType> GraphTypes { get; }

        public ReadOnlyObservableCollection<WaterQualityVO> WaterQualityList { get; set; }

        private double _totalEnergy;
        public double TotalEnergy
        {
            get => _totalEnergy;
            set
            {
                if (_totalEnergy != value)
                {
                    _totalEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalSandFilterEnergy;
        public double TotalSandFilterEnergy
        {
            get => _totalSandFilterEnergy;
            set
            {
                if (_totalSandFilterEnergy != value)
                {
                    _totalSandFilterEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalCirculationPumpEnergy;
        public double TotalCirculationPumpEnergy
        {
            get => _totalCirculationPumpEnergy;
            set
            {
                if (_totalCirculationPumpEnergy != value)
                {
                    _totalCirculationPumpEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalHeatPumpEnergy;
        public double TotalHeatPumpEnergy
        {
            get => _totalHeatPumpEnergy;
            set
            {
                if (_totalHeatPumpEnergy != value)
                {
                    _totalHeatPumpEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalAirBlowerEnergy;
        public double TotalAirBlowerEnergy
        {
            get => _totalAirBlowerEnergy;
            set
            {
                if (_totalAirBlowerEnergy != value)
                {
                    _totalAirBlowerEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalOzoneGeneratorEnergy;
        public double TotalOzoneGeneratorEnergy
        {
            get => _totalOzoneGeneratorEnergy;
            set
            {
                if (_totalOzoneGeneratorEnergy != value)
                {
                    _totalOzoneGeneratorEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalUVSterilizerEnergy;
        public double TotalUVSterilizerEnergy
        {
            get => _totalUVSterilizerEnergy;
            set
            {
                if (_totalUVSterilizerEnergy != value)
                {
                    _totalUVSterilizerEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalOzoneDissolverEnergy;
        public double TotalOzoneDissolverEnergy
        {
            get => _totalOzoneDissolverEnergy;
            set
            {
                if (_totalOzoneDissolverEnergy != value)
                {
                    _totalOzoneDissolverEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _totalExcessOzoneDestroyerEnergy;
        public double TotalExcessOzoneDestroyerEnergy
        {
            get => _totalExcessOzoneDestroyerEnergy;
            set
            {
                if (_totalExcessOzoneDestroyerEnergy != value)
                {
                    _totalExcessOzoneDestroyerEnergy = value;
                    OnPropertyChanged();
                }
            }
        }

        private int _selectedGraphIndex = -1;
        public int SelectedGraphIndex
        {
            get => _selectedGraphIndex;
            set
            {
                if (_selectedGraphIndex != value)
                {
                    _selectedGraphIndex = value;
                    OnPropertyChanged();
                    // 인덱스가 바뀌면 enum도 맞춰준다
                    if (value >= 0 && value < GraphTypes.Count)
                        SelectedGraphType = GraphTypes[value];
                }
            }
        }

        private GraphType _selectedGraphType;
        public GraphType SelectedGraphType
        {
            get => _selectedGraphType;
            set
            {
                if (_selectedGraphType != value)
                {
                    _selectedGraphType = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowXSelector));
                    RebuildFieldCandidates();

                    var idx = GraphTypes.IndexOf(value);
                    if (idx != -1 && idx != _selectedGraphIndex)
                    {
                        _selectedGraphIndex = idx;
                        OnPropertyChanged(nameof(SelectedGraphIndex));
                    }
                }
            }
        }

        private StepFieldKind _selectedKind = StepFieldKind.Energy; // 기본값은 센서
        public StepFieldKind SelectedKind
        {
            get => _selectedKind;
            set
            {
                if (_selectedKind != value)
                {
                    _selectedKind = value;
                    OnPropertyChanged();
                }
            }
        }

        public bool ShowXSelector => SelectedGraphType == GraphType.SCATTER;

        // [필드 후보 목록] 탭/시스템에 따라 달라짐
        public ObservableCollection<FieldItem> AvailableFields { get; } = new();

        // [X축 후보/선택]
        public ObservableCollection<FieldItem> XFieldCandidates { get; } = new();
        private FieldItem? _selectedXField;
        public FieldItem? SelectedXField
        {
            get => _selectedXField;
            set { if (_selectedXField != value) { _selectedXField = value; OnPropertyChanged(); } }
        }

        // [Y축 후보/선택] — Line/Step: 다중, Scatter/Box: 단일
        public ObservableCollection<FieldItem> YFieldCandidates { get; } = new();

        // 다중 선택(Y)용
        public ObservableCollection<FieldItem> SelectedYFields { get; } = new();

        // 단일 선택(Y)용
        private FieldItem? _selectedYField;
        public FieldItem? SelectedYField
        {
            get => _selectedYField;
            set { if (_selectedYField != value) { _selectedYField = value; OnPropertyChanged(); } }
        }

        private bool _useAverage;
        public bool UseAverage { get => _useAverage; set { _useAverage = value; OnPropertyChanged(); } }

        private bool _showMarkers;
        public bool ShowMarkers { get => _showMarkers; set { _showMarkers = value; OnPropertyChanged(); } }

        private bool _showLegends;
        public bool ShowLegends { get => _showLegends; set { _showLegends = value; OnPropertyChanged(); } }

        private bool _isDonut;
        public bool IsDonut { get => _isDonut; set { _isDonut = value; OnPropertyChanged(); } }

        public ICommand DrawGraphCommand { get; }


        public EnergyViewModel() 
        {
            GraphTypes = new ObservableCollection<GraphType>
            {
                GraphType.LINE,
                GraphType.STACKAREA,
                GraphType.PIE
            };

            WaterQualityList = Datas.Instance.WaterQualityView;

            TotalSandFilterEnergy = WaterQualityList.Sum(vo => vo.Filtering.SandFilterEnergy);           
            TotalCirculationPumpEnergy = WaterQualityList.Sum(vo => vo.Filtering.CirculationPumpEnergy);
            TotalHeatPumpEnergy = WaterQualityList.Sum(vo => vo.Filtering.HeatPumpEnergy);
            TotalAirBlowerEnergy = WaterQualityList.Sum(vo => vo.Filtering.AirBlowerEnergy);
            TotalOzoneGeneratorEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.OzoneGeneratorEnergy);
            TotalUVSterilizerEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.UVSterilizerEnergy);
            TotalOzoneDissolverEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.OzoneDissolverEnergy);
            TotalExcessOzoneDestroyerEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.ExcessOzoneDestroyerEnergy);
            TotalEnergy = WaterQualityList.Sum(vo => vo.TotalEnergy);

            SelectedKind = StepFieldKind.Energy; // 기본적으로 에너지 관련 필드만 표시

            DrawGraphCommand = new RelayCommand(DrawGraph);

            RebuildAvailableFields();
            RebuildFieldCandidates();
        }

        private void DrawGraph(object obj)
        {
            switch (SelectedGraphType)
            {
                case GraphType.LINE:
                    GraphControlVM.SetMultiLineGraph(WaterQualityList.ToList(), SelectedYFields, DataType.Energy, ShowMarkers, ShowLegends);
                    break;
                case GraphType.STACKAREA:
                    GraphControlVM.SetStackAreaPlot(WaterQualityList.ToList(), SelectedYFields, DataType.Energy, ShowMarkers, ShowLegends);
                    break;
                case GraphType.PIE:
                    GraphControlVM.SetPieChart(WaterQualityList.ToList(), SelectedYFields, DataType.Energy, UseAverage, IsDonut);
                    break;
                default:
                    break;
            }
        }

        private void RebuildAvailableFields()
        {
            AvailableFields.Clear();

            // 공통 시간
            AvailableFields.Add(new FieldItem { Name = "RecordedTime", Display = "시간", DataType = typeof(DateTime) });

            AvailableFields.Add(new FieldItem { Name = "TotalEnergy", Display = "총 전력", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Filtering.SandFilterEnergy", Display = "모래여과기", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Filtering.CirculationPumpEnergy", Display = "순환펌프", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Filtering.HeatPumpEnergy", Display = "히트펌프", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Filtering.AirBlowerEnergy", Display = "에어브로와", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.OzoneGeneratorEnergy", Display = "오존발생기", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.UVSterilizerEnergy", Display = "자외선 살균기", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.OzoneDissolverEnergy", Display = "오존용해장치", DataType = typeof(double), Kind = StepFieldKind.Energy });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.ExcessOzoneDestroyerEnergy", Display = "배오존장치", DataType = typeof(double), Kind = StepFieldKind.Energy });
        }

        private void RebuildFieldCandidates()
        {
            // 후보 초기화
            XFieldCandidates.Clear();
            YFieldCandidates.Clear();

            // X축: 시간 우선
            foreach (var f in AvailableFields)
            {
                XFieldCandidates.Add(f);
                if (SelectedGraphType == GraphType.LINE || SelectedGraphType == GraphType.STACKAREA) break;
            }
            SelectedXField = AvailableFields.FirstOrDefault(f => f.DataType == typeof(DateTime))
                             ?? AvailableFields.FirstOrDefault();

            IEnumerable<FieldItem> src = AvailableFields.Where(f => f.Kind == SelectedKind);

            if (SelectedGraphType is GraphType.LINE or GraphType.STACKAREA or GraphType.PIE)
            {
                // 수치형만 (LINE/STACKAREA/PIE 연속값 위주)
                src = src.Where(f => f.DataType == typeof(double));
            }

            // Y축 후보: 수치형
            foreach (var f in src)
            {
                if (SelectedGraphType is GraphType.STACKAREA or GraphType.PIE && f.Name.Equals("TotalEnergy")) continue; 
                YFieldCandidates.Add(f);
            }

            // 기본 선택 세팅 (타입별)
            SelectedYFields.Clear();
            SelectedYField = null;

            switch (SelectedGraphType)
            {
                case GraphType.LINE:
                    //var def = YFieldCandidates.FirstOrDefault();
                    //if (def != null) SelectedYFields.Add(def);
                    break;
                case GraphType.STACKAREA:
                    SelectedYField = YFieldCandidates.FirstOrDefault();
                    break;

                case GraphType.PIE:
                    //SelectedYField = YFieldCandidates.FirstOrDefault();
                    break;
            }
            OnPropertyChanged(nameof(SelectedYFields));
        }

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