using MainShell.AlgorithmCalib.Common;
using MainShell.AlgorithmCalib.Model;
using MainShell.AlgorithmCalib.Service;
using MainShell.Common;
using MainShell.Common.Display.ViewModel;
using MainShell.Hardware;
using MainShell.Motion;
using Maxwell.SemiFramework.DefaultConfig.Vision;
using MwFramework.Controls.ControlCanvas.Model;
using MwFramework.Device;
using SemiconductorVisionAlgorithm.SemiParams;
using Stylet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace MainShell.AlgorithmCalib.ViewModel
{
    /// <summary>
    /// 对标 OriginCalibModuleViewModel（模块卡片VM）
    /// 原 RotateFormCalibViewModel 中模块级逻辑 + 原 Task 的编排逻辑搬到这里
    /// </summary>
    public class RotateMatixFormModuleViewModel : PropertyChangedBase
    {
        private const string CalibrationDialogCaption = "旋转表标定";

        private readonly HardwareManager _hardware;
        private readonly RotateMatixFormCalibMotionService _motionService;
        private readonly RotateMatixFormCalibModuleItem _item;
        private readonly ApproachAlignmentService _approachAlignmentService;
        private readonly Func<Rectangle1> _roiRectProvider;  // ROI 提供者委托

        private int _index;
        private bool _isCalibrating;
        private bool _isWritten;
        private CancellationTokenSource _cts;

        public RotateMatixFormCalibModuleItem Item => _item;

        #region 对标 OriginCalibModuleViewModel 的通用属性

        public int Index
        {
            get { return _index; }
            set { SetAndNotify(ref _index, value); }
        }

        public string ModuleName
        {
            get { return _item.ModuleName; }
            set { _item.ModuleName = value; NotifyOfPropertyChange(nameof(ModuleName)); }
        }

        public bool IsCalibrating
        {
            get { return _isCalibrating; }
            set
            {
                SetAndNotify(ref _isCalibrating, value);
                NotifyOfPropertyChange(nameof(CanStartCalib));
            }
        }

        public bool IsWritten
        {
            get { return _isWritten; }
            set
            {
                SetAndNotify(ref _isWritten, value);
            }
        }

        public bool CanStartCalib => !IsCalibrating;

        private bool _isCalibrated;
        public bool IsCalibrated
        {
            get { return _isCalibrated; }
            set
            {
                SetAndNotify(ref _isCalibrated, value);
                NotifyOfPropertyChange(nameof(CanWriteToController));
            }
        }

        public bool CanWriteToController => !IsCalibrating && _isCalibrated;

        #endregion

        #region 旋转表标定特有参数（绑定到 View）

        public double X1AvoidancePosition
        {
            get { return _item.X1AvoidancePosition; }
            set { _item.X1AvoidancePosition = value; NotifyOfPropertyChange(nameof(X1AvoidancePosition)); }
        }

        public double RotateStep
        {
            get { return _item.RotateStep; }
            set { _item.RotateStep = value; NotifyOfPropertyChange(nameof(RotateStep)); }
        }

        public double WaferStep
        {
            get { return _item.WaferStep; }
            set { _item.WaferStep = value; NotifyOfPropertyChange(nameof(WaferStep)); }
        }

        public int RowCol
        {
            get { return _item.RowCol; }
            set { _item.RowCol = value; NotifyOfPropertyChange(nameof(RowCol)); }
        }

        public int VerifyRowCol
        {
            get { return _item.VerifyRowCol; }
            set { _item.VerifyRowCol = value; NotifyOfPropertyChange(nameof(VerifyRowCol)); }
        }

        public double VerifyWaferStep
        {
            get { return _item.VerifyWaferStep; }
            set { _item.VerifyWaferStep = value; NotifyOfPropertyChange(nameof(VerifyWaferStep)); }
        }

        public double VerifyRotateRange
        {
            get { return _item.VerifyRotateRange; }
            set { _item.VerifyRotateRange = value; NotifyOfPropertyChange(nameof(VerifyRotateRange)); }
        }

        public double StartX
        {
            get { return _item.StartX; }
            set { _item.StartX = value; NotifyOfPropertyChange(nameof(StartX)); }
        }

        public double StartY
        {
            get { return _item.StartY; }
            set { _item.StartY = value; NotifyOfPropertyChange(nameof(StartY)); }
        }

        public double VerifyStartX
        {
            get { return _item.VerifyStartX; }
            set { _item.VerifyStartX = value; NotifyOfPropertyChange(nameof(VerifyStartX)); }
        }

        public double VerifyStartY
        {
            get { return _item.VerifyStartY; }
            set { _item.VerifyStartY = value; NotifyOfPropertyChange(nameof(VerifyStartY)); }
        }

        #endregion

        #region 标定进度

        private string _progressMessage = "";
        public string ProgressMessage
        {
            get { return _progressMessage; }
            set { SetAndNotify(ref _progressMessage, value); }
        }

        private int _progressCurrent;
        public int ProgressCurrent
        {
            get { return _progressCurrent; }
            set { SetAndNotify(ref _progressCurrent, value); }
        }

        private int _progressTotal;
        public int ProgressTotal
        {
            get { return _progressTotal; }
            set
            {
                SetAndNotify(ref _progressTotal, value);
                NotifyOfPropertyChange(nameof(ProgressPercentage));
                NotifyOfPropertyChange(nameof(ProgressText));
            }
        }

        public double ProgressPercentage => ProgressTotal > 0
            ? (double)ProgressCurrent / ProgressTotal * 100
            : 0;

        public string ProgressText => ProgressTotal > 0
            ? $"{ProgressCurrent}/{ProgressTotal}"
            : "";

        private bool _isProgressVisible;
        public bool IsProgressVisible
        {
            get { return _isProgressVisible; }
            set { SetAndNotify(ref _isProgressVisible, value); }
        }
        #endregion

        public RotateMatixFormModuleViewModel(
            RotateMatixFormCalibModuleItem item,
            HardwareManager hardware,
            RotateMatixFormCalibMotionService motionService,
            ApproachAlignmentService approachAlignmentService,
            Func<Rectangle1> roiRectProvider)
        {
            _item = item ?? throw new ArgumentNullException(nameof(item));
            _hardware = hardware ?? throw new ArgumentNullException(nameof(hardware));
            _motionService = motionService ?? throw new ArgumentNullException(nameof(motionService));
            _approachAlignmentService = approachAlignmentService ?? throw new ArgumentNullException(nameof(approachAlignmentService));
            _roiRectProvider = roiRectProvider;
            SubscribeToProgress();
        }
        private void SubscribeToProgress()
        {
            if (_item.PostProcessor is RotateMatixFormCalibPostProcessor processor)
            {
                processor.ProgressChanged += OnProgressChanged;
            }
        }

        private void UnsubscribeFromProgress()
        {
            if (_item.PostProcessor is RotateMatixFormCalibPostProcessor processor)
            {
                processor.ProgressChanged -= OnProgressChanged;
            }
        }

        private void OnProgressChanged(object sender, CalibrationProgressEventArgs e)
        {
            // 切换到 UI 线程更新
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                ProgressMessage = e.Message;
                ProgressCurrent = e.Current;
                ProgressTotal = e.Total;
                NotifyOfPropertyChange(nameof(ProgressPercentage));
                NotifyOfPropertyChange(nameof(ProgressText));
            });
        }

        #region 对标 OriginCalibModuleViewModel 的通用方法

        public void ResetModule()
        {
            IsCalibrated = false;
            IsWritten = false;
            NotifyOfPropertyChange(nameof(CanWriteToController));
        }
        #endregion

        #region 旋转表标定特有操作（原 ViewModel 按钮方法）

        /// <summary>
        /// 原 btnMoveToPosPosition()
        /// 移动 X1 到避让位 + 移动 WS 到起始位置
        /// </summary>
        public void MoveToPosition()
        {
            Task.Run(() =>
            {
                try
                {
                    _motionService.SafeMove(_hardware.Axis_PHS_X1, X1AvoidancePosition);
                    _motionService.MoveWsAvoidance(StartX, StartY);
                }
                catch (Exception ex)
                {
                    MwMessageBox.Show($"移动失败：{ex.Message}", CalibrationDialogCaption,
                        MessageBoxButton.OK, MessageBoxImage.Error);
                }
            });
        }

        /// <summary>
        /// 原 btnMoveToCenterPoint()
        /// 中心对齐，读取并设置 StartX, StartY
        /// </summary>
        public void MoveToCenterPoint()
        {
            Task.Run(async () =>
            {
                try
                {
                    bool success = await FindPointCircleAsync(CancellationToken.None);
                    if (success)
                    {
                        StartX = _hardware.Axis_PHS_X2.State.ActualPos;
                        StartY = _hardware.Axis_PHS_Y1.State.ActualPos;
                        MwMessageBox.Show($"对齐值，X2:{StartX},Y1:{StartY}");
                    }
                    else
                    {
                        MwMessageBox.Show("对齐失败！");
                    }
                }
                catch (Exception ex)
                {
                    MwMessageBox.Show($"异常：{ex.Message}");
                }
            });
        }

        /// <summary>
        /// 原 btnVerifyApproachCenter()
        /// 验证对齐
        /// </summary>
        public void VerifyApproachCenter()
        {
            Task.Run(async () =>
            {
                try
                {
                    bool success = await FindPointCircleAsync(CancellationToken.None);
                    if (success)
                    {
                        VerifyStartX = _hardware.Axis_PHS_X2.State.ActualPos;
                        VerifyStartY = _hardware.Axis_PHS_Y1.State.ActualPos;
                        MwMessageBox.Show($"对齐值，X2:{StartX},Y1:{StartY}");
                    }
                    else
                    {
                        MwMessageBox.Show("对齐失败！");
                    }
                }
                catch (Exception ex)
                {
                    MwMessageBox.Show($"异常：{ex.Message}");
                }
            });
        }

        #endregion

        #region 核心标定流程（对标 StartCalib）

        /// <summary>
        /// 对标 OriginCalibModuleViewModel.StartCalib()
        /// 原 btnStart() + RotateFormCalibTask.RotateCalib() 的编排逻辑
        /// </summary>
        public async Task StartCalib()
        {
            if (IsCalibrating) return;
            IsCalibrating = true;
            IsProgressVisible = true;  // 显示进度
            _cts = new CancellationTokenSource();

            try
            {
                // 标定流程（原 RotateFormCalibTask.RotateCalib 的编排）
                if (_item.PostProcessor != null)
                {
                    await ((RotateMatixFormCalibPostProcessor)_item.PostProcessor)
                        .ExecuteAsync(null, _cts.Token);
                }
                IsWritten = false;
            }
            catch (OperationCanceledException)
            {
                MwMessageBox.Show("标定已取消。", CalibrationDialogCaption,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            catch (Exception ex)
            {
                MwMessageBox.Show($"标定失败：{ex.Message}", CalibrationDialogCaption,
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                IsCalibrating = false;
                IsProgressVisible = false;  // 隐藏进度
            }
        }

        /// <summary>
        /// 原 btnVerifyStart() + RotateFormCalibTask.RotateCalibVerify()
        /// </summary>
        public async Task StartVerify()
        {
            if (IsCalibrating) return;
            IsCalibrating = true;
            IsProgressVisible = true;  // 显示进度
            _cts = new CancellationTokenSource();

            try
            {
                if (_item.PostProcessor != null)
                {
                    await ((RotateMatixFormCalibPostProcessor)_item.PostProcessor)
                        .VerifyAsync(_cts.Token);
                }
            }
            catch (OperationCanceledException)
            {
                MwMessageBox.Show("验证已取消。", CalibrationDialogCaption,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            catch (Exception ex)
            {
                MwMessageBox.Show($"验证失败：{ex.Message}", CalibrationDialogCaption,
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                IsCalibrating = false;
                IsProgressVisible = false;  // 隐藏进度
            }
        }

        /// <summary>
        /// 原 btnStop() / btnVerifyStop()
        /// </summary>
        public void Stop()
        {
            _cts?.Cancel();
        }

        #endregion

        #region 私有辅助方法

        /// <summary>
        /// 原 FindPointCircle()
        /// </summary>
        private async Task<bool> FindPointCircleAsync(CancellationToken token)
        {
            Rectangle1 roiRect = _roiRectProvider?.Invoke();
            var request = new ApproachAlignmentRequest(
                axes: new[]
                {
                new ApproachAlignmentAxis(GetAxisName(_hardware.Axis_X2), 0.005),
                new ApproachAlignmentAxis(GetAxisName(_hardware.Axis_Y1), 0.005)
                },
                camera: CameraType.TopPositionCamera)
            {
                MaxIterations = 3,
                RecognitionTimeoutMilliseconds = 5000,
                RecognitionParameters = new CenterRecognitionParameters()
                {
                    Type = CenterRecognitionType.EdgeCircle,
                    rectangle = roiRect
                }
            };

            var result = await _approachAlignmentService
                .ApproachAlignmentAsync(request, token);
            return result.Succeeded;
        }

        private static string GetAxisName(IAxis axis)
        {
            if (axis == null)
            {
                return string.Empty;
            }

            return axis.Name;
        }
        #endregion
    }
}
