using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using SmartAquaViewer.Controls;
using SmartAquaViewer.DataAnalysis;
using SmartAquaViewer.Model;

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

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

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

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

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

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

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

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

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

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

        private double _totalExcessOzoneDestroyerGreenhouseGas;
        public double TotalExcessOzoneDestroyerGreenhouseGas
        {
            get => _totalExcessOzoneDestroyerGreenhouseGas;
            set
            {
                if (_totalExcessOzoneDestroyerGreenhouseGas != value)
                {
                    _totalExcessOzoneDestroyerGreenhouseGas = 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.GHG; // 기본값은 센서
        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 _showMarkers;                 // Line
        public bool ShowMarkers { get => _showMarkers; set { _showMarkers = value; OnPropertyChanged(); } }

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

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

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

        public ICommand DrawGraphCommand { get; }

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

            WaterQualityList = Datas.Instance.WaterQualityView;


            TotalSandFilterGreenhouseGas = WaterQualityList.Sum(vo => vo.Filtering.SandFilterGreenhouseGas);
            TotalCirculationPumpGreenhouseGas = WaterQualityList.Sum(vo => vo.Filtering.CirculationPumpGreenhouseGas);
            TotalHeatPumpGreenhouseGas = WaterQualityList.Sum(vo => vo.Filtering.HeatPumpGreenhouseGas);
            TotalAirBlowerGreenhouseGas = WaterQualityList.Sum(vo => vo.Filtering.AirBlowerGreenhouseGas);
            TotalOzoneGeneratorGreenhouseGas = WaterQualityList.Sum(vo => vo.Sterilizing.OzoneGeneratorGreenhouseGas);
            TotalUVSterilizerGreenhouseGas = WaterQualityList.Sum(vo => vo.Sterilizing.UVSterilizerGreenhouseGas);
            TotalOzoneDissolverGreenhouseGas = WaterQualityList.Sum(vo => vo.Sterilizing.OzoneDissolverGreenhouseGas);
            TotalExcessOzoneDestroyerGreenhouseGas = WaterQualityList.Sum(vo => vo.Sterilizing.ExcessOzoneDestroyerGreenhouseGas);
            TotalGreenhouseGas = WaterQualityList.Sum(vo => vo.TotalGreenhouseGas);

            SelectedKind = StepFieldKind.GHG;

            DrawGraphCommand = new RelayCommand(DrawGraph);

            RebuildAvailableFields();
            RebuildFieldCandidates();
        }

        private void DrawGraph(object obj)
        {
            switch (SelectedGraphType)
            {
                case GraphType.LINE:
                    GraphControlVM.SetMultiLineGraph(WaterQualityList.ToList(), SelectedYFields, DataType.GreenhouseGas, ShowMarkers, ShowLegends);
                    break;
                case GraphType.STACKAREA:
                    GraphControlVM.SetStackAreaPlot(WaterQualityList.ToList(), SelectedYFields, DataType.GreenhouseGas, ShowMarkers, ShowLegends);
                    break;
                case GraphType.PIE:
                    GraphControlVM.SetPieChart(WaterQualityList.ToList(), SelectedYFields, DataType.GreenhouseGas, 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 = "TotalGreenhouseGas", Display = "총 배출량", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Filtering.SandFilterGreenhouseGas", Display = "모래여과기", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Filtering.CirculationPumpGreenhouseGas", Display = "순환펌프", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Filtering.HeatPumpGreenhouseGas", Display = "히트펌프", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Filtering.AirBlowerGreenhouseGas", Display = "에어브로와", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.OzoneGeneratorGreenhouseGas", Display = "오존발생기", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.UVSterilizerGreenhouseGas", Display = "자외선 살균기", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.OzoneDissolverGreenhouseGas", Display = "오존용해장치", DataType = typeof(double), Kind = StepFieldKind.GHG });
            AvailableFields.Add(new FieldItem { Name = "Sterilizing.ExcessOzoneDestroyerGreenhouseGas", Display = "배오존장치", DataType = typeof(double), Kind = StepFieldKind.GHG });
        }

        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;

            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("TotalGreenhouseGas")) 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));
    }
}
