using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using Model.Entity;
using ORM;
using SqlSugar;
using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.ViewModelBase;

namespace MonitorModule.ViewModels
{
    /// <summary>
    /// 记录界面：查询 MonitorValueEntity 表中的历史监测数据。
    /// 功能：监测项筛选 / 台架筛选 / 日期筛选 / 分页 / 导出 CSV。
    /// 使用 SqlSugarContext.DbContext 全局单例，与写入端共用同一数据库连接。
    /// </summary>
    public class RecordViewModel : NavigateViewModelBase, IRegionMemberLifetime, IDisposable
    {

        #region 属性
        public bool KeepAlive => true;
        public ScopedContext _scopedContext { get; set; }
        public GlobalInfo _globalInfo { get; }

        public string TestStatus
        {
            get => _testStatus;
            set => SetProperty(ref _testStatus, value);
        }

        /// <summary>监测项名称下拉列表</summary>
        public ObservableCollection<string> MonitorNames
        {
            get => _monitorNames;
            set => SetProperty(ref _monitorNames, value);
        }

        /// <summary>选中的监测项（null = 全部）</summary>
        public string? SelectedMonitorName
        {
            get => _selectedMonitorName;
            set => SetProperty(ref _selectedMonitorName, value);
        }

        /// <summary>台架（作用域）下拉列表</summary>
        public ObservableCollection<string> ScopeNames
        {
            get => _scopeNames;
            set => SetProperty(ref _scopeNames, value);
        }

        /// <summary>选中的台架（null = 全部）</summary>
        public string? SelectedScope
        {
            get => _selectedScope;
            set => SetProperty(ref _selectedScope, value);
        }

        /// <summary>查询日期（null = 全部日期）</summary>
        public DateTime? SelectedStartDate
        {
            get => _selectedStartDate;
            set => SetProperty(ref _selectedStartDate, value);
        }   
        public DateTime? SelectedEndDate
        {
            get => _selectedEndDate;
            set => SetProperty(ref _selectedEndDate, value);
        }

        public DataTable ResultTable
        {
            get => _resultTable;
            set => SetProperty(ref _resultTable, value);
        }

        public string StatusMessage
        {
            get => _statusMessage;
            set => SetProperty(ref _statusMessage, value);
        }

        public int PageIndex
        {
            get => _pageIndex;
            set => SetProperty(ref _pageIndex, value);
        }

        public int PageSize
        {
            get => _pageSize;
            set
            {
                if (SetProperty(ref _pageSize, value <= 0 ? 50 : value))
                {
                    RaisePropertyChanged(nameof(TotalPages));
                    PageIndex = 1;
                    Query();
                }
            }
        }

        public long TotalCount
        {
            get => _totalCount;
            set
            {
                SetProperty(ref _totalCount, value);
                RaisePropertyChanged(nameof(TotalPages));
            }
        }

        public int TotalPages
        {
            get
            {
                if (PageSize <= 0) return 1;
                var pages = (int)((TotalCount + PageSize - 1) / PageSize);
                return pages <= 0 ? 1 : pages;
            }
        }
        #endregion

        #region 命令
        public ICommand LoadedCommand { get; }
        public ICommand QueryCommand { get; }
        public ICommand ClearFilterCommand { get; }
        public ICommand FirstPageCommand { get; }
        public ICommand PrevPageCommand { get; }
        public ICommand NextPageCommand { get; }
        public ICommand LastPageCommand { get; }
        public ICommand ExportCsvCommand { get; }
        public ICommand RefreshCommand { get; }
        #endregion

        #region 私有字段
        private IScopedProvider _scope;
        private string _testStatus = string.Empty;
        private ObservableCollection<string> _monitorNames = new();
        private string? _selectedMonitorName;
        private ObservableCollection<string> _scopeNames = new(new[] { "全部", "TestCell1", "TestCell2", "TestCell3", "TestCell4", "TestCell5", "TestCell6", "TestCell7", "TestCell8" });
        private string? _selectedScope = "全部";
        private DateTime? _selectedStartDate;
        private DateTime? _selectedEndDate;
        private DataTable _resultTable = new();
        private string _statusMessage = "未连接";
        private int _pageIndex = 1;
        private int _pageSize = 50;
        private long _totalCount;
        private bool IsInitiated = false;
        #endregion

        public RecordViewModel(IContainerExtension container) : base(container)
        {
            _globalInfo = container.Resolve<GlobalInfo>();
            LoadedCommand = new DelegateCommand(LoadFilterOptions);
            QueryCommand = new DelegateCommand(() => { PageIndex = 1; Query(); });
            ClearFilterCommand = new DelegateCommand(ClearFilter);
            FirstPageCommand = new DelegateCommand(() => { if (PageIndex > 1) { PageIndex = 1; Query(); } });
            PrevPageCommand = new DelegateCommand(() => { if (PageIndex > 1) { PageIndex--; Query(); } });
            NextPageCommand = new DelegateCommand(() => { if (PageIndex < TotalPages) { PageIndex++; Query(); } });
            LastPageCommand = new DelegateCommand(() => { if (PageIndex < TotalPages) { PageIndex = TotalPages; Query(); } });
            ExportCsvCommand = new DelegateCommand(ExportCsv);
            RefreshCommand = new DelegateCommand(OnExpand);
        }

        public void Dispose()
        {
            _scope?.Dispose();
        }

        #region 筛选条件加载
        /// <summary>
        /// 加载筛选条件：监测项通过反射发现（与 MonitorViewModel 一致），台架从数据库查询。
        /// </summary>
        private void LoadFilterOptions()
        {
            // 监测项：反射发现当前作用域所有带 [Monitorable] 的设备方法
            DiscoverMonitorNames();

            Query();
        }

        /// <summary>
        /// 反射扫描当前作用域 DeviceManager 中所有带 [Monitorable] 特性的设备方法，
        /// 生成与 MonitorViewModel 完全一致的 DisplayName 列表，填充到下拉框。
        /// 这样即使数据库还没数据，用户也能看到所有可筛选的监测项。
        /// </summary>
        private void DiscoverMonitorNames()
        {
            MonitorNames = new ObservableCollection<string>();

            if (_scope == null) return;

            try
            {
                var deviceManager = _scope.Resolve<DeviceManager>();
                if (deviceManager?.DeviceMap == null || deviceManager.DeviceMap.Count == 0)
                {
                    StatusMessage = "当前工位无可用设备";
                    return;
                }

                // 构建 设备实例 → 硬件指纹 的反向查找表
                var instanceToFp = new Dictionary<object, string>(ReferenceEqualityComparer.Instance);
                foreach (var poolEntry in _globalInfo.HardwarePool)
                {
                    var lazy = poolEntry.Value;
                    if (lazy.IsValueCreated && lazy.Value != null)
                        instanceToFp[lazy.Value] = poolEntry.Key;
                }

                var names = new List<string>();

                foreach (var kvp in deviceManager.DeviceMap)
                {
                    string deviceName = kvp.Key;
                    var device = kvp.Value;
                    var deviceType = device.GetType();

                    // 只列出在硬件指纹池中注册的设备
                    if (!instanceToFp.ContainsKey(device))
                        continue;

                    var methods = deviceType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                        .Where(m =>
                        {
                            if (m.GetCustomAttribute<MonitorableAttribute>() == null) return false;
                            if (m.ReturnType != typeof(Task<string>)) return false;
                            var parms = m.GetParameters();
                            return parms.Length == 0 ||
                                   (parms.Length == 1 && parms[0].ParameterType == typeof(CancellationToken));
                        });

                    foreach (var method in methods)
                    {
                        var attr = method.GetCustomAttribute<MonitorableAttribute>();
                        string displayName = !string.IsNullOrEmpty(attr?.Description)
                            ? $"{deviceName}.{attr.Description}"
                            : $"{deviceName}.{method.Name}";
                        names.Add(displayName);
                    }
                }

                names.Sort();
                MonitorNames = new ObservableCollection<string>(names);
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"反射发现监测项失败：{ex.Message}");
            }
        }

        /// <summary>清除所有筛选条件</summary>
        private void ClearFilter()
        {
            SelectedMonitorName = null;
            SelectedScope = "全部";
            SelectedStartDate = null;
            SelectedEndDate = null;
            PageIndex = 1;
            Query();
        }
        #endregion

        #region 查询
        /// <summary>
        /// 按当前筛选条件分页查询 MonitorValueEntity。
        /// </summary>
        private void Query()
        {
            try
            {
                var db = SqlSugarContext.DbContext;

                // 预计算日期范围，避免在表达式树中访问可空属性
                DateTime? dateStart = SelectedStartDate?.Date;
                DateTime? dateEnd = SelectedEndDate?.Date.AddDays(1);

                var query = db.Queryable<MonitorValueEntity>()
                    .WhereIF(!string.IsNullOrEmpty(SelectedMonitorName), x => x.MonitorName == SelectedMonitorName)
                    .WhereIF(!string.IsNullOrEmpty(SelectedScope) && SelectedScope != "全部", x => x.Scope == SelectedScope)
                    .WhereIF(dateStart.HasValue, x => x.CreateTime >= dateStart && x.CreateTime < dateEnd!.Value)
                    .OrderBy(x => x.CreateTime, OrderByType.Desc);

                TotalCount = query.Count();

                // 修正越界
                if (PageIndex > TotalPages) PageIndex = TotalPages;
                if (PageIndex < 1) PageIndex = 1;

                int skip = (PageIndex - 1) * PageSize;
                ResultTable = query
                    .Skip(skip)
                    .Take(PageSize)
                    .ToDataTable();

                StatusMessage = $"共 {TotalCount} 行  第 {PageIndex}/{TotalPages} 页";
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(TestStatus, $"查询失败：{ex.Message}");
                StatusMessage = $"查询失败：{ex.Message}";
                ResultTable = new DataTable();
                TotalCount = 0;
            }
        }
        #endregion

        #region 导出 CSV
        /// <summary>
        /// 按当前筛选条件导出全部结果到 CSV（不分页）。
        /// </summary>
        private void ExportCsv()
        {
            try
            {
                var db = SqlSugarContext.DbContext;

                DateTime? dateStart = SelectedStartDate?.Date;
                DateTime? dateEnd = SelectedEndDate?.Date.AddDays(1);

                var query = db.Queryable<MonitorValueEntity>()
                    .WhereIF(!string.IsNullOrEmpty(SelectedMonitorName), x => x.MonitorName == SelectedMonitorName)
                    .WhereIF(!string.IsNullOrEmpty(SelectedScope) && SelectedScope != "全部", x => x.Scope == SelectedScope)
                    .WhereIF(dateStart.HasValue, x => x.CreateTime >= dateStart && x.CreateTime < dateEnd!.Value)
                    .OrderBy(x => x.CreateTime, OrderByType.Desc);

                var dt = query.ToDataTable();
                if (dt.Rows.Count == 0)
                {
                    StatusMessage = "无可导出数据";
                    return;
                }

                var dlg = new Microsoft.Win32.SaveFileDialog
                {
                    Filter = "CSV 文件 (*.csv)|*.csv|所有文件|*.*",
                    FileName = $"MonitorData_{DateTime.Now:yyyyMMdd_HHmmss}.csv",
                    Title = "导出监测数据为 CSV"
                };
                if (dlg.ShowDialog() != true) return;

                WriteCsv(dlg.FileName, dt);

                StatusMessage = $"导出完成：{dlg.FileName}（{dt.Rows.Count} 行）";
                LoggerHelper.InfoWithNotify(TestStatus, $"工位 [{TestStatus}] 导出监测数据至 {dlg.FileName}，共 {dt.Rows.Count} 行");
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(TestStatus, $"导出失败：{ex.Message}");
                StatusMessage = $"导出失败：{ex.Message}";
            }
        }

        private static void WriteCsv(string path, DataTable dt)
        {
            // 写 UTF-8 BOM 让 Excel 直接识别中文
            using var sw = new StreamWriter(path, false, new UTF8Encoding(true));
            // 表头
            sw.WriteLine(string.Join(",", dt.Columns.Cast<DataColumn>().Select(c => Escape(c.ColumnName))));
            // 行
            foreach (DataRow row in dt.Rows)
            {
                sw.WriteLine(string.Join(",", row.ItemArray.Select(v => Escape(v?.ToString() ?? string.Empty))));
            }
        }

        private static string Escape(string field)
        {
            if (field.Contains('"') || field.Contains(',') || field.Contains('\r') || field.Contains('\n'))
            {
                return "\"" + field.Replace("\"", "\"\"") + "\"";
            }
            return field;
        }
        #endregion

        #region 双击展开
        private void OnExpand()
        {
            if (string.IsNullOrEmpty(TestStatus)) return;
            _globalInfo.CurrentScope = TestStatus;
            _eventAggregator.GetEvent<ExpandViewEvent>().Publish(TestStatus);
        }
        #endregion

        #region 重写
        public override void OnNavigatedTo(NavigationContext navigationContext)
        {
            base.OnNavigatedTo(navigationContext);
            if (!IsInitiated && navigationContext.Parameters.ContainsKey("Name"))
            {
                TestStatus = navigationContext.Parameters.GetValue<string>("Name");
                _scope = _globalInfo.ScopeDic[TestStatus];
                _scopedContext = _scope.Resolve<ScopedContext>();
                IsInitiated = true;
            }
            LoadFilterOptions();
        }
        #endregion
    }
}
