using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using XP.Common.Logging.Interfaces;
using XP.Hardware.Detector.Abstractions;
using XP.Hardware.Detector.Abstractions.Enums;
using XP.Hardware.Detector.Abstractions.Events;
using XP.Hardware.Detector.Services;

namespace XP.Hardware.Detector.ViewModels
{
    /// <summary>
    /// 探测器操作 ViewModel | Detector operation ViewModel
    /// 负责连接/断开、连续采集、单帧采集、图像显示及状态跟踪
    /// </summary>
    public class DetectorImageWindowViewModel : BindableBase
    {
        private readonly IDetectorService _detectorService;
        private readonly IEventAggregator _eventAggregator;
        private readonly IImageService _imageSaveService;
        private readonly ILoggerService _logger;

        /// <summary>
        /// 帧处理节流标志，防止后台线程堆积 | Frame processing throttle flag to prevent thread pile-up
        /// 0 = 空闲，1 = 正在处理
        /// </summary>
        private int _isProcessingFrame;

        #region 连接状态 | Connection status

        private bool _isConnected;
        /// <summary>
        /// 探测器是否已连接 | Whether detector is connected
        /// </summary>
        public bool IsConnected
        {
            get => _isConnected;
            private set
            {
                if (SetProperty(ref _isConnected, value))
                {
                    RaiseAllCommandsCanExecuteChanged();
                    RaisePropertyChanged(nameof(ConnectionStatusText));
                    RaisePropertyChanged(nameof(ConnectionStatusColor));
                }
            }
        }

        /// <summary>
        /// 连接状态文本 | Connection status text
        /// </summary>
        public string ConnectionStatusText => _isConnected ? "已连接 | Connected" : "未连接 | Disconnected";

        /// <summary>
        /// 连接状态指示颜色 | Connection status indicator color
        /// </summary>
        public Brush ConnectionStatusColor => _isConnected
            ? new SolidColorBrush(Color.FromRgb(0x4C, 0xAF, 0x50))   // 绿色 | Green
            : new SolidColorBrush(Color.FromRgb(0xF4, 0x43, 0x36));  // 红色 | Red

        #endregion

        #region 探测器状态 | Detector status

        private DetectorStatus _detectorStatus = DetectorStatus.Uninitialized;
        /// <summary>
        /// 当前探测器状态 | Current detector status
        /// </summary>
        public DetectorStatus DetectorStatus
        {
            get => _detectorStatus;
            private set
            {
                if (SetProperty(ref _detectorStatus, value))
                {
                    RaisePropertyChanged(nameof(DetectorStatusText));
                    RaiseAllCommandsCanExecuteChanged();
                }
            }
        }

        /// <summary>
        /// 探测器状态文本 | Detector status text
        /// </summary>
        public string DetectorStatusText => _detectorStatus switch
        {
            Abstractions.Enums.DetectorStatus.Uninitialized => "未初始化 | Uninitialized",
            Abstractions.Enums.DetectorStatus.Initializing  => "初始化中 | Initializing",
            Abstractions.Enums.DetectorStatus.Ready         => "就绪 | Ready",
            Abstractions.Enums.DetectorStatus.Acquiring     => "采集中 | Acquiring",
            Abstractions.Enums.DetectorStatus.Correcting    => "校正中 | Correcting",
            Abstractions.Enums.DetectorStatus.Error         => "错误 | Error",
            _                                               => "未知 | Unknown"
        };

        #endregion

        #region 探测器信息 | Detector info

        private string _detectorModel = "--";
        /// <summary>
        /// 探测器型号 | Detector model
        /// </summary>
        public string DetectorModel
        {
            get => _detectorModel;
            private set => SetProperty(ref _detectorModel, value);
        }

        private string _detectorResolution = "--";
        /// <summary>
        /// 探测器分辨率 | Detector resolution
        /// </summary>
        public string DetectorResolution
        {
            get => _detectorResolution;
            private set => SetProperty(ref _detectorResolution, value);
        }

        private string _detectorPixelSize = "--";
        /// <summary>
        /// 探测器像素尺寸 | Detector pixel size
        /// </summary>
        public string DetectorPixelSize
        {
            get => _detectorPixelSize;
            private set => SetProperty(ref _detectorPixelSize, value);
        }

        private string _detectorType = "--";
        /// <summary>
        /// 探测器类型 | Detector type
        /// </summary>
        public string DetectorTypeText
        {
            get => _detectorType;
            private set => SetProperty(ref _detectorType, value);
        }

        #endregion

        #region 图像属性 | Image properties

        private BitmapSource _imageSource;
        /// <summary>
        /// 当前显示的图像 | Currently displayed image
        /// </summary>
        public BitmapSource ImageSource
        {
            get => _imageSource;
            private set => SetProperty(ref _imageSource, value);
        }

        private int _frameNumber;
        /// <summary>
        /// 当前帧号 | Current frame number
        /// </summary>
        public int FrameNumber
        {
            get => _frameNumber;
            private set => SetProperty(ref _frameNumber, value);
        }

        private string _imageInfo = "等待采集... | Waiting for acquisition...";
        /// <summary>
        /// 图像信息文本 | Image info text
        /// </summary>
        public string ImageInfo
        {
            get => _imageInfo;
            private set => SetProperty(ref _imageInfo, value);
        }

        private bool _isAcquiring;
        /// <summary>
        /// 是否正在连续采集 | Whether continuous acquisition is in progress
        /// </summary>
        public bool IsAcquiring
        {
            get => _isAcquiring;
            private set
            {
                if (SetProperty(ref _isAcquiring, value))
                    RaiseAllCommandsCanExecuteChanged();
            }
        }

        #endregion

        #region 操作忙碌状态 | Operation busy state

        private bool _isBusy;
        /// <summary>
        /// 是否正在执行连接/断开操作 | Whether connect/disconnect is in progress
        /// </summary>
        public bool IsBusy
        {
            get => _isBusy;
            private set
            {
                if (SetProperty(ref _isBusy, value))
                    RaiseAllCommandsCanExecuteChanged();
            }
        }

        private string _statusMessage = "";
        /// <summary>
        /// 操作状态消息 | Operation status message
        /// </summary>
        public string StatusMessage
        {
            get => _statusMessage;
            private set => SetProperty(ref _statusMessage, value);
        }

        #endregion

        #region 命令 | Commands

        /// <summary>
        /// 连接探测器命令 | Connect detector command
        /// </summary>
        public DelegateCommand ConnectCommand { get; }

        /// <summary>
        /// 断开探测器命令 | Disconnect detector command
        /// </summary>
        public DelegateCommand DisconnectCommand { get; }

        /// <summary>
        /// 启动连续采集命令 | Start continuous acquisition command
        /// </summary>
        public DelegateCommand StartAcquisitionCommand { get; }

        /// <summary>
        /// 停止采集命令 | Stop acquisition command
        /// </summary>
        public DelegateCommand StopAcquisitionCommand { get; }

        /// <summary>
        /// 单帧采集命令 | Single frame acquisition command
        /// </summary>
        public DelegateCommand SingleFrameCommand { get; }

        /// <summary>
        /// 保存图像命令 | Save image command
        /// </summary>
        public DelegateCommand SaveImageCommand { get; }

        #endregion

        #region 构造函数 | Constructor

        public DetectorImageWindowViewModel(
            IDetectorService detectorService,
            IEventAggregator eventAggregator,
            IImageService imageSaveService,
            ILoggerService logger)
        {
            _detectorService = detectorService ?? throw new ArgumentNullException(nameof(detectorService));
            _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
            _imageSaveService = imageSaveService ?? throw new ArgumentNullException(nameof(imageSaveService));
            _logger = logger?.ForModule<DetectorImageWindowViewModel>() ?? throw new ArgumentNullException(nameof(logger));

            ConnectCommand = new DelegateCommand(ExecuteConnectAsync, CanExecuteConnect);
            DisconnectCommand = new DelegateCommand(ExecuteDisconnectAsync, CanExecuteDisconnect);
            StartAcquisitionCommand = new DelegateCommand(ExecuteStartAcquisitionAsync, CanExecuteStartAcquisition);
            StopAcquisitionCommand = new DelegateCommand(ExecuteStopAcquisitionAsync, CanExecuteStopAcquisition);
            SingleFrameCommand = new DelegateCommand(ExecuteSingleFrameAsync, CanExecuteSingleFrame);
            SaveImageCommand = new DelegateCommand(ExecuteSaveImageAsync, CanExecuteSaveImage);

            // 订阅图像采集事件（后台线程）| Subscribe to image captured event (background thread)
            // 图像转换在后台线程执行，避免阻塞 UI | Image conversion runs on background thread to avoid blocking UI
            _eventAggregator.GetEvent<ImageCapturedEvent>()
                .Subscribe(OnImageCaptured, ThreadOption.BackgroundThread);

            // 订阅探测器状态变更事件 | Subscribe to detector status changed event
            _eventAggregator.GetEvent<StatusChangedEvent>()
                .Subscribe(OnDetectorStatusChanged, ThreadOption.UIThread);

            // 同步初始状态 | Sync initial state
            SyncStatusFromService();
        }

        #endregion

        #region CanExecute

        private bool CanExecuteConnect()    => !_isBusy && !_isConnected;
        private bool CanExecuteDisconnect() => !_isBusy && _isConnected && !_isAcquiring;
        private bool CanExecuteStartAcquisition() => !_isBusy && _isConnected &&
                                                     _detectorStatus == Abstractions.Enums.DetectorStatus.Ready &&
                                                     !_isAcquiring;
        private bool CanExecuteStopAcquisition()  => _isConnected && _isAcquiring;
        private bool CanExecuteSingleFrame()      => !_isBusy && _isConnected &&
                                                     _detectorStatus == Abstractions.Enums.DetectorStatus.Ready &&
                                                     !_isAcquiring;
        private bool CanExecuteSaveImage()        => _isConnected && _imageSaveService.LatestFrame != null;

        private void RaiseAllCommandsCanExecuteChanged()
        {
            ConnectCommand.RaiseCanExecuteChanged();
            DisconnectCommand.RaiseCanExecuteChanged();
            StartAcquisitionCommand.RaiseCanExecuteChanged();
            StopAcquisitionCommand.RaiseCanExecuteChanged();
            SingleFrameCommand.RaiseCanExecuteChanged();
            SaveImageCommand.RaiseCanExecuteChanged();
        }

        #endregion

        #region 命令执行 | Command execution

        /// <summary>
        /// 连接探测器 | Connect detector
        /// </summary>
        private async void ExecuteConnectAsync()
        {
            _logger?.Info("开始连接探测器 | Connecting detector");
            IsBusy = true;
            StatusMessage = "正在连接探测器... | Connecting...";
            try
            {
                var result = await _detectorService.InitializeAsync();
                if (result.IsSuccess)
                {
                    IsConnected = true;
                    StatusMessage = "探测器连接成功，正在应用参数... | Detector connected, applying parameters...";
                    _logger?.Info("探测器连接成功 | Detector connected successfully");
                    RefreshDetectorInfo();

                    // 连接成功后自动应用持久化的探测器参数 | Auto apply saved detector parameters after connection
                    var saved = Config.ConfigLoader.LoadSavedParameters();
                    if (saved.HasValue)
                    {
                        var (binIdx, pga, fr, _) = saved.Value;
                        var applyResult = await _detectorService.ApplyParametersAsync(binIdx, pga, fr);
                        if (applyResult.IsSuccess)
                        {
                            StatusMessage = "探测器就绪 | Detector ready";
                            _logger?.Info("探测器参数已自动应用，Binning={Binning}，PGA={PGA}，帧率={FrameRate} | Detector parameters auto-applied", binIdx, pga, fr);
                        }
                        else
                        {
                            StatusMessage = $"参数应用失败：{applyResult.ErrorMessage}";
                            _logger?.Warn("自动应用参数失败：{Message} | Auto apply parameters failed: {Message}", applyResult.ErrorMessage);
                        }
                    }
                    else
                    {
                        StatusMessage = "探测器就绪（使用默认参数）| Detector ready (default parameters)";
                        _logger?.Info("未找到持久化参数，使用默认配置 | No saved parameters found, using default config");
                    }
                }
                else
                {
                    StatusMessage = $"连接失败：{result.ErrorMessage}";
                    _logger?.Error(result.Exception, "探测器连接失败：{Message} | Detector connection failed: {Message}", result.ErrorMessage);
                }
            }
            catch (Exception ex)
            {
                StatusMessage = $"连接异常：{ex.Message}";
                _logger?.Error(ex, "探测器连接异常：{Message} | Detector connection exception: {Message}", ex.Message);
            }
            finally
            {
                IsBusy = false;
            }
        }

        /// <summary>
        /// 断开探测器 | Disconnect detector
        /// </summary>
        private async void ExecuteDisconnectAsync()
        {
            _logger?.Info("开始断开探测器 | Disconnecting detector");
            IsBusy = true;
            StatusMessage = "正在断开探测器... | Disconnecting...";
            try
            {
                var result = await _detectorService.DisconnectAsync();
                IsConnected = false;
                IsAcquiring = false;
                ClearDetectorInfo();
                ImageInfo = "等待采集... | Waiting for acquisition...";

                if (result.IsSuccess)
                {
                    StatusMessage = "探测器已断开 | Detector disconnected";
                    _logger?.Info("探测器已断开 | Detector disconnected");
                }
                else
                {
                    StatusMessage = $"断开时发生错误：{result.ErrorMessage}";
                    _logger?.Warn("断开探测器时发生错误：{Message} | Error during disconnect: {Message}", result.ErrorMessage);
                }
            }
            catch (Exception ex)
            {
                IsConnected = false;
                IsAcquiring = false;
                ClearDetectorInfo();
                StatusMessage = $"断开异常：{ex.Message}";
                _logger?.Error(ex, "断开探测器异常：{Message} | Disconnect exception: {Message}", ex.Message);
            }
            finally
            {
                IsBusy = false;
            }
        }

        /// <summary>
        /// 启动连续采集 | Start continuous acquisition
        /// </summary>
        private async void ExecuteStartAcquisitionAsync()
        {
            _logger?.Info("启动连续采集 | Starting continuous acquisition");
            IsAcquiring = true;
            StatusMessage = "采集中... | Acquiring...";
            try
            {
                var result = await _detectorService.StartAcquisitionAsync();
                if (!result.IsSuccess)
                {
                    IsAcquiring = false;
                    StatusMessage = $"启动采集失败：{result.ErrorMessage}";
                    _logger?.Error(result.Exception, "启动采集失败：{Message} | Start acquisition failed: {Message}", result.ErrorMessage);
                }
            }
            catch (Exception ex)
            {
                IsAcquiring = false;
                StatusMessage = $"启动采集异常：{ex.Message}";
                _logger?.Error(ex, "启动采集异常：{Message} | Start acquisition exception: {Message}", ex.Message);
            }
        }

        /// <summary>
        /// 停止采集 | Stop acquisition
        /// </summary>
        private async void ExecuteStopAcquisitionAsync()
        {
            _logger?.Info("停止采集 | Stopping acquisition");
            StatusMessage = "正在停止采集... | Stopping...";
            try
            {
                var result = await _detectorService.StopAcquisitionAsync();
                IsAcquiring = false;
                StatusMessage = result.IsSuccess ? "采集已停止 | Acquisition stopped" : $"停止采集失败：{result.ErrorMessage}";
                if (!result.IsSuccess)
                    _logger?.Error(result.Exception, "停止采集失败：{Message} | Stop acquisition failed: {Message}", result.ErrorMessage);
            }
            catch (Exception ex)
            {
                IsAcquiring = false;
                StatusMessage = $"停止采集异常：{ex.Message}";
                _logger?.Error(ex, "停止采集异常：{Message} | Stop acquisition exception: {Message}", ex.Message);
            }
        }

        /// <summary>
        /// 单帧采集 | Single frame acquisition
        /// </summary>
        private async void ExecuteSingleFrameAsync()
        {
            _logger?.Info("单帧采集 | Single frame acquisition");
            IsBusy = true;
            StatusMessage = "单帧采集中... | Acquiring single frame...";
            try
            {
                var result = await _detectorService.AcquireSingleFrameAsync();
                StatusMessage = result.IsSuccess ? "单帧采集完成 | Single frame acquired" : $"单帧采集失败：{result.ErrorMessage}";
                if (!result.IsSuccess)
                    _logger?.Error(result.Exception, "单帧采集失败：{Message} | Single frame failed: {Message}", result.ErrorMessage);
            }
            catch (Exception ex)
            {
                StatusMessage = $"单帧采集异常：{ex.Message}";
                _logger?.Error(ex, "单帧采集异常：{Message} | Single frame exception: {Message}", ex.Message);
            }
            finally
            {
                IsBusy = false;
            }
        }

        /// <summary>
        /// 保存当前图像为 16 位 TIFF | Save current image as 16-bit TIFF
        /// </summary>
        private async void ExecuteSaveImageAsync()
        {
            var frame = _imageSaveService.LatestFrame;
            if (frame?.ImageData == null)
            {
                StatusMessage = "无可保存的图像 | No image to save";
                return;
            }

            _logger?.Info("保存图像，帧号：{FrameNumber} | Saving image, frame: {FrameNumber}", frame.FrameNumber);
            StatusMessage = "正在保存图像... | Saving image...";
            try
            {
                var saveDir = _imageSaveService.GetDefaultSaveDirectory();
                var result = await _imageSaveService.SaveLatestFrameAsync(saveDir, "IMG");

                StatusMessage = result.IsSuccess
                    ? $"图像已保存 | Image saved"
                    : $"保存失败：{result.ErrorMessage}";
            }
            catch (Exception ex)
            {
                StatusMessage = $"保存异常：{ex.Message}";
                _logger?.Error(ex, "保存图像异常：{Message} | Save image exception: {Message}", ex.Message);
            }
        }

        #endregion

        #region 事件回调 | Event callbacks

        /// <summary>
        /// 图像采集回调，将 16 位原始数据归一化为 8 位灰度图 | Image captured callback
        /// </summary>
        private void OnImageCaptured(ImageCapturedEventArgs args)
        {
            if (args?.ImageData == null || args.Width == 0 || args.Height == 0) return;

            // 帧节流：上一帧尚未被 UI 线程消费完毕时，跳过当前帧
            // Frame throttle: skip current frame if previous frame hasn't been consumed by UI thread yet
            if (Interlocked.CompareExchange(ref _isProcessingFrame, 1, 0) != 0) return;

            try
            {
                // 在后台线程执行图像转换 | Perform image conversion on background thread
                var bitmap = ConvertToBitmapSource(args.ImageData, (int)args.Width, (int)args.Height);
                bitmap.Freeze(); // Freeze 后可跨线程访问 | Freeze allows cross-thread access

                var frameNumber = args.FrameNumber;
                var imageInfo = $"{args.Width}×{args.Height}  帧#{args.FrameNumber}  {args.CaptureTime:HH:mm:ss.fff}";

                // 将属性赋值调度到 UI 线程，完成后才释放节流标志
                // Dispatch property assignment to UI thread; release throttle flag only after UI completes
                Application.Current?.Dispatcher?.BeginInvoke(new Action(() =>
                {
                    try
                    {
                        ImageSource = bitmap;
                        FrameNumber = frameNumber;
                        ImageInfo = imageInfo;
                    }
                    finally
                    {
                        // UI 线程完成渲染后才允许下一帧进入 | Allow next frame only after UI thread finishes rendering
                        Interlocked.Exchange(ref _isProcessingFrame, 0);
                    }
                }));
            }
            catch (Exception ex)
            {
                // 异常时释放标志，避免永久锁死 | Release flag on exception to avoid permanent lock
                Interlocked.Exchange(ref _isProcessingFrame, 0);
                _logger?.Error(ex, "图像转换失败：{Message} | Image conversion failed: {Message}", ex.Message);
            }
        }

        /// <summary>
        /// 探测器状态变更回调 | Detector status changed callback
        /// </summary>
        private void OnDetectorStatusChanged(DetectorStatus status)
        {
            DetectorStatus = status;

            // 根据状态同步 IsAcquiring | Sync IsAcquiring from status
            if (status == Abstractions.Enums.DetectorStatus.Acquiring)
                IsAcquiring = true;
            else if (status == Abstractions.Enums.DetectorStatus.Ready ||
                     status == Abstractions.Enums.DetectorStatus.Error)
                IsAcquiring = false;

            // 探测器错误时同步连接状态 | Sync connection state on error
            if (status == Abstractions.Enums.DetectorStatus.Uninitialized)
            {
                IsConnected = false;
                ClearDetectorInfo();
            }
        }

        #endregion

        #region 私有辅助方法 | Private helpers

        /// <summary>
        /// 从服务层同步当前状态（ViewModel 初始化时调用）| Sync state from service (called on init)
        /// </summary>
        private void SyncStatusFromService()
        {
            IsConnected = _detectorService.IsConnected;
            DetectorStatus = _detectorService.Status;
            if (IsConnected)
                RefreshDetectorInfo();
        }

        /// <summary>
        /// 刷新探测器信息显示 | Refresh detector info display
        /// </summary>
        private void RefreshDetectorInfo()
        {
            try
            {
                var info = _detectorService.GetInfo();
                if (info == null) return;

                DetectorModel = string.IsNullOrEmpty(info.Model) ? "--" : info.Model;
                DetectorResolution = (info.MaxWidth > 0 && info.MaxHeight > 0)
                    ? $"{info.MaxWidth}×{info.MaxHeight}"
                    : "--";
                DetectorPixelSize = info.PixelSize > 0
                    ? $"{info.PixelSize:F3} mm"
                    : "--";
                DetectorTypeText = _detectorService.Type?.ToString() ?? "--";
            }
            catch (Exception ex)
            {
                _logger?.Warn("获取探测器信息失败：{Message} | Failed to get detector info: {Message}", ex.Message);
            }
        }

        /// <summary>
        /// 清空探测器信息 | Clear detector info
        /// </summary>
        private void ClearDetectorInfo()
        {
            DetectorModel = "--";
            DetectorResolution = "--";
            DetectorPixelSize = "--";
            DetectorTypeText = "--";
        }

        /// <summary>
        /// 将 16 位灰度数据转换为 8 位 BitmapSource（委托给 XP.Common 通用转换器）
        /// Convert 16-bit grayscale data to 8-bit BitmapSource (delegates to XP.Common common converter)
        /// </summary>
        private static BitmapSource ConvertToBitmapSource(ushort[] data, int width, int height)
        {
            return XP.Common.Converters.ImageConverter.ConvertGray16ToBitmapSource(data, width, height);
        }

        #endregion
    }
}
