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 MainShell.PageCalib.OriginCalib.Service;
using MaxwellFramework.Core.Interfaces;
using MwFramework.Controls.ControlCanvas.Model;
using MwFramework.Device;
using MwFramework.ManagerService;
using SemiconductorVisionAlgorithm.SemiParams;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using CameraAxisViewModel = MainShell.Common.Display.ViewModel.CameraAxisViewModel;
using SemiPoint = SemiconductorVisionAlgorithm.SemiParams.Point;

namespace MainShell.AlgorithmCalib.ViewModel
{
    /// <summary>
    /// 融合标定子窗口VM（Die/Pad共用）
    /// 对标 MotionCalibViewModel
    /// </summary>
    public class FusionCalibViewModel : Screen, IPage
    {
        private readonly FusionCalibMotionService _fusionCalibMotionService;
        private readonly HardwareManager _hardware;
        private CancellationTokenSource _cts;

        public string Name { get; set; } = "FusionCalib";
        public string CalibName { get; set; }
        public string CameraName { get; set; }
        public string FileSaveDir { get; set; }

        // 是否Wafer标定（true=Die用WS轴, false=Pad用PHS轴）
        public bool IsWaferCalib { get; private set; }

        #region 属性

        private FusionCalibModuleItem _moduleItem = new FusionCalibModuleItem();
        public FusionCalibModuleItem ModuleItem
        {
            get => _moduleItem;
            set => SetAndNotify(ref _moduleItem, value);
        }

        // PadFusionCalibView 绑定这个
        public FusionCalibModuleItem FusionCalibParItem
        {
            get => _moduleItem;
            set { _moduleItem = value; NotifyOfPropertyChange(nameof(FusionCalibParItem)); }
        }

        // DieFusionCalibView 绑定这个
        public FusionCalibModuleItem WsFusionCalibParItem
        {
            get => _moduleItem;
            set { _moduleItem = value; NotifyOfPropertyChange(nameof(WsFusionCalibParItem)); }
        }

        private CameraAxisViewModel _cameraAxisViewModelSevice;
        public CameraAxisViewModel CameraAxisViewModelSevice
        {
            get => _cameraAxisViewModelSevice;
            set => SetAndNotify(ref _cameraAxisViewModelSevice, value);
        }

        private DelegateBase _motion = new DelegateBase();
        public DelegateBase Motion
        {
            get => _motion;
            set => SetAndNotify(ref _motion, value);
        }

        private FusionCalibPostProcessor _postProcessor;
        public FusionCalibPostProcessor PostProcessor
        {
            get => _postProcessor;
            set => SetAndNotify(ref _postProcessor, value);
        }

        private ApproachAlignmentService _approachAlignmentService;
        public ApproachAlignmentService ApproachAlignmentService
        {
            get => _approachAlignmentService;
            set => SetAndNotify(ref _approachAlignmentService, value);
        }

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

        public bool CanStartCalib => !IsCalibrating;

        #endregion

        #region 进度

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

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

        private int _progressTotal;
        public int ProgressTotal
        {
            get => _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 => _isProgressVisible;
            set => SetAndNotify(ref _isProgressVisible, value);
        }

        #endregion

        #region 构造 & 工厂

        public FusionCalibViewModel() { }

        public FusionCalibViewModel(HardwareManager hardware, FusionCalibMotionService motion)
        {
            _hardware = hardware;
            _fusionCalibMotionService = motion;
            _approachAlignmentService = IoC.Get<ApproachAlignmentService>();
        }

        /// <summary>
        /// Die融合用：单页面模式
        /// </summary>
        public static FusionCalibViewModel Create(string calibName, string saveFileName,
            List<HardwareDevice> device, HardwareManager hardware,
            FusionCalibMotionService motion, bool isWaferCalib)
        {
            var vm = new FusionCalibViewModel(hardware, motion);
            vm.CalibName = calibName;
            vm.FileSaveDir = saveFileName;
            vm.IsWaferCalib = isWaferCalib;

            vm.CameraAxisViewModelSevice = IoC.Get<CameraAxisViewModel>();
            vm.CameraAxisViewModelSevice.CameraAxisDevices.HardwareDeviceList = device;
            
            vm.ModuleItem = new FusionCalibModuleItem
            {
                ModuleName = isWaferCalib ? FusionCalibModuleNames.DieFusion : FusionCalibModuleNames.PadFusion,
                Camera_ID = hardware.TopWsCameraExtend.Id ,
                IsWaferCalib = isWaferCalib,
                CalibStep = 0.4,
                CalibCount = 10,
                Count = 4,
                Step = 5.0,
            };

            vm.PostProcessor = new FusionCalibPostProcessor(motion, hardware, vm.ModuleItem, vm.GetRoiRect);
            vm.SubscribeToProgress();
            return vm;
        }

        /// <summary>
        /// Pad融合用：子窗口模式
        /// </summary>
        public static FusionCalibViewModel Create(string calibName,
            List<HardwareDevice> device, FusionCalibModuleItem param,
            HardwareManager hardware, FusionCalibMotionService motion, bool isWaferCalib)
        {
            var vm = new FusionCalibViewModel(hardware, motion);
            vm.CalibName = calibName;
            vm.CameraName = hardware.TopCameraExtend.Id;
            vm.IsWaferCalib = isWaferCalib;
            vm.ModuleItem = param;

            vm.CameraAxisViewModelSevice = IoC.Get<CameraAxisViewModel>();
            vm.CameraAxisViewModelSevice.CameraAxisDevices.HardwareDeviceList = device;

            vm.PostProcessor = new FusionCalibPostProcessor(motion, hardware, param, vm.GetRoiRect);
            vm.SubscribeToProgress();
            return vm;
        }

        #endregion

        #region 进度订阅

        private void SubscribeToProgress()
        {
            if (PostProcessor != null) PostProcessor.ProgressChanged += OnProgressChanged;
        }

        private void UnsubscribeFromProgress()
        {
            if (PostProcessor != null) PostProcessor.ProgressChanged -= OnProgressChanged;
        }

        private void OnProgressChanged(object sender, CalibrationProgressEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                ProgressMessage = e.Message;
                ProgressCurrent = e.Current;
                ProgressTotal = e.Total;
                NotifyOfPropertyChange(nameof(ProgressPercentage));
                NotifyOfPropertyChange(nameof(ProgressText));
            });
        }

        #endregion

        #region 按钮操作（Die/Pad共用逻辑，XAML通过不同View绑定）

        public void btnMoveWSCalibPosPosition() => MoveToCalibPos();
        public void btnMovePhsCalibPosPosition() => MoveToCalibPos();

        private void MoveToCalibPos()
        {
            Task.Run(() =>
            {
                try
                {
                    if (IsWaferCalib)
                    {
                        // Die: 移动X1到标定位置，然后移动X2,Y1到逼近位置
                        _fusionCalibMotionService.SafeMove(_hardware.Axis_X1, ModuleItem.MoveAxisPos);
                        _fusionCalibMotionService.MoveWsAvoidance(ModuleItem.ApproachXPos, ModuleItem.ApproachYPos);
                    }
                    else
                    {
                        // Pad: 移动Y1到标定位置，然后移动X1,Y2到逼近位置
                        _fusionCalibMotionService.SafeMove(_hardware.Axis_Y1, ModuleItem.MoveAxisPos);
                        _fusionCalibMotionService.MovePhsAvoidance(ModuleItem.ApproachXPos, ModuleItem.ApproachYPos);
                    }
                }
                catch (Exception ex) { MwMessageBox.Show($"移动失败：{ex.Message}"); }
            });
        }

        public void btnApproachWSCalibPosition() => DoApproach();
        public void btnApproachPhsCalibPosition() => DoApproach();

        private void DoApproach()
        {
            Task.Run(async () =>
            {
                try
                {
                    bool success = await FindPointCircleAsync(CancellationToken.None);
                    if (success)
                    {
                        if (IsWaferCalib)
                        {

                            // Die: 读取当前X2,Y1位置作为逼近值
                            ModuleItem.ApproachXPos = _hardware.Axis_X2.State.ActualPos;
                            ModuleItem.ApproachYPos = _hardware.Axis_Y1.State.ActualPos;
                        }
                        else
                        {
                            // Pad: 读取当前X1,Y2位置作为逼近值
                            ModuleItem.ApproachXPos = _hardware.Axis_X1.State.ActualPos;
                            ModuleItem.ApproachYPos = _hardware.Axis_Y2.State.ActualPos;
                        }
                        MwMessageBox.Show($"对齐值，X:{ModuleItem.ApproachXPos},Y:{ModuleItem.ApproachYPos}");
                    }
                    else
                    {
                        MwMessageBox.Show("对齐失败！");
                    }
                }
                catch (Exception ex) { MwMessageBox.Show($"异常：{ex.Message}"); }
            });
        }

        public void btnCalculateCameraPosition()
        {
            try
            {
                int offset = -10;
                double minPos = 0;
                if (IsWaferCalib)
                {
                    // Die: 计算X1相机轴起始位置
                    _hardware.Axis_X2.GetSoftMel(ref minPos);
                    var delx = ModuleItem.ApproachXPos - minPos + offset;
                    ModuleItem.CameraAxisPos = ModuleItem.MoveAxisPos - delx;
                }
                else
                {
                    // Pad: 计算Y1相机轴起始位置
                    _hardware.Axis_Y2.GetSoftMel(ref minPos);
                    var delx = ModuleItem.ApproachYPos - minPos + offset;
                    ModuleItem.CameraAxisPos = ModuleItem.MoveAxisPos - delx;
                }
            }
            catch (Exception ex) { MwMessageBox.Show($"计算失败：{ex.Message}"); }
        }

        public void btnSetCameraPosition()
        {
            if (MwMessageBox.Show("是否使用当前位置?", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                // Die: 读取X1当前位置  Pad: 读取Y1当前位置
                ModuleItem.CameraAxisPos = IsWaferCalib
                    ? _hardware.Axis_X1.State.ActualPos
                    : _hardware.Axis_Y1.State.ActualPos;
            }
        }

        public void btnMoveCameraPosition()
        {
            if (MwMessageBox.Show("是否移动到该点?", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                Task.Run(() =>
                {
                    try
                    {
                        // Die: 移动X1  Pad: 移动Y1
                        if (IsWaferCalib)
                            _fusionCalibMotionService.SafeMove(_hardware.Axis_X1, ModuleItem.CameraAxisPos);
                        else
                            _fusionCalibMotionService.SafeMove(_hardware.Axis_Y1, ModuleItem.CameraAxisPos);
                    }
                    catch (Exception ex) { MwMessageBox.Show($"移动失败：{ex.Message}"); }
                });
            }
        }

        public void btnCalculateWSPosition() => CalculateStartPositions();
        public void btnCalculatePhsPosition() => CalculateStartPositions();

        private void CalculateStartPositions()
        {
            try
            {
                int offset = -10;
                double minPos = 0;
                if (IsWaferCalib)
                {
                    // Die: 计算WS起始位置
                    _hardware.Axis_X2.GetSoftMel(ref minPos);
                    var delx = ModuleItem.ApproachXPos - minPos + offset;
                    ModuleItem.CameraAxisPos = ModuleItem.MoveAxisPos - delx;
                    double x11Offset = ModuleItem.CameraAxisPos - ModuleItem.MoveAxisPos;
                    ModuleItem.StartX = ModuleItem.ApproachXPos + x11Offset;
                    ModuleItem.StartY = ModuleItem.ApproachYPos;
                }
                else
                {
                    // Pad: 计算PHS起始位置
                    _hardware.Axis_Y2.GetSoftMel(ref minPos);
                    var delx = ModuleItem.ApproachYPos - minPos + offset;
                    ModuleItem.CameraAxisPos = ModuleItem.MoveAxisPos - delx;
                    double y11Offset = ModuleItem.CameraAxisPos - ModuleItem.MoveAxisPos;
                    ModuleItem.StartX = ModuleItem.ApproachXPos;
                    ModuleItem.StartY = ModuleItem.ApproachYPos + y11Offset;
                }
            }
            catch (Exception ex) { MwMessageBox.Show($"计算失败：{ex.Message}"); }
        }

        public void btnSetWaferStartPosition() => SetCurrentPos();
        public void btnSetStageStartPosition() => SetCurrentPos();

        private void SetCurrentPos()
        {
            if (MwMessageBox.Show("是否使用当前位置?", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                Task.Run(() =>
                {
                    if (IsWaferCalib)
                    {
                        // Die: 读取X2,Y1当前位置
                        ModuleItem.StartX = _hardware.Axis_X2.State.ActualPos;
                        ModuleItem.StartY = _hardware.Axis_Y1.State.ActualPos;
                    }
                    else
                    {
                        // Pad: 读取X1,Y2当前位置
                        ModuleItem.StartX = _hardware.Axis_X1.State.ActualPos;
                        ModuleItem.StartY = _hardware.Axis_Y2.State.ActualPos;
                    }
                });
            }
        }

        public void btnMoveWaferStartPosition() => MoveToStart();
        public void btnMoveStageStartPosition() => MoveToStart();

        private void MoveToStart()
        {
            if (MwMessageBox.Show("是否移动到该点?", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                if (IsWaferCalib)
                    _fusionCalibMotionService.MoveWsAvoidance(ModuleItem.StartX, ModuleItem.StartY);
                else
                    _fusionCalibMotionService.MovePhsAvoidance(ModuleItem.StartX, ModuleItem.StartY);
            }
        }

        public void btnMoveToCenter()
        {
            Task.Run(() =>
            {
                try
                {
                    if (IsWaferCalib)
                    {
                        ModuleItem.WaferStartVerifyX = _hardware.Axis_X2.State.ActualPos;
                        ModuleItem.WaferStartVerifyY = _hardware.Axis_Y1.State.ActualPos;
                    }
                    else
                    {
                        ModuleItem.WaferStartVerifyX = _hardware.Axis_X1.State.ActualPos;
                        ModuleItem.WaferStartVerifyY = _hardware.Axis_Y2.State.ActualPos;
                    }
                    MwMessageBox.Show("设置起点完成");
                }
                catch (Exception ex) { MwMessageBox.Show($"设置失败：{ex.Message}"); }
            });
        }

        #endregion

        #region 验证流程

        private bool _stopVerifyMotion = false;

        public void btnMoveToStartPoint()
        {
            if (MwMessageBox.Show("是否移动到验证起点?", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                try
                {
                    if (IsWaferCalib)
                        _fusionCalibMotionService.MoveWsAvoidance(ModuleItem.WaferStartVerifyX, ModuleItem.WaferStartVerifyY);
                    else
                        _fusionCalibMotionService.MovePhsAvoidance(ModuleItem.WaferStartVerifyX, ModuleItem.WaferStartVerifyY);
                }
                catch (Exception ex) { MwMessageBox.Show($"移动失败：{ex.Message}"); }
            }
        }

        public void btnMoveWafer()
        {
            ModuleItem.RulerPoints = new List<SemiPoint>();
            ModuleItem.RealPoints = new List<SemiPoint>();

            Task.Run(() =>
            {
                try
                {
                    _stopVerifyMotion = false;

                    for (int i = 0; i < ModuleItem.WaferVerityCountY; i++)
                    {
                        for (int j = 0; j < ModuleItem.WaferVerityCountX; j++)
                        {
                            if (_stopVerifyMotion)
                            {
                                _stopVerifyMotion = false;
                                return;
                            }

                            double yPos = ModuleItem.WaferStartVerifyY + i * ModuleItem.WaferVerityStep;
                            double xPos;
                            if (i % 2 == 0)
                                xPos = ModuleItem.WaferStartVerifyX + j * ModuleItem.WaferVerityStep;
                            else
                                xPos = ModuleItem.WaferStartVerifyX + (ModuleItem.WaferVerityCountX - j - 1) *
ModuleItem.WaferVerityStep;

                            if (IsWaferCalib)
                                _fusionCalibMotionService.MoveWsAvoidance(xPos, yPos);
                            else
                                _fusionCalibMotionService.MovePhsAvoidance(xPos, yPos);

                            // TODO: 调用逼近识别 ApproachPointCircle
                            if (IsWaferCalib)
                            {
                                SemiPoint ruler = new SemiPoint(_hardware.Axis_X2.State.ActualPos,
_hardware.Axis_Y1.State.ActualPos);
                                ModuleItem.RulerPoints.Add(ruler);
                            }
                            else
                            {
                                SemiPoint ruler = new SemiPoint(_hardware.Axis_X1.State.ActualPos,
_hardware.Axis_Y2.State.ActualPos);
                                ModuleItem.RulerPoints.Add(ruler);
                            }
                        }
                    }
                    MwMessageBox.Show("飞拍结束");
                }
                catch (Exception ex) { MwMessageBox.Show($"飞拍失败：{ex.Message}"); }
            });
        }

        public void btnVerityWafer()
        {
            if (ModuleItem.RulerPoints == null || ModuleItem.RulerPoints.Count == 0)
            {
                MwMessageBox.Show("请先执行飞拍！");
                return;
            }

            if (MwMessageBox.Show("是否已移动到对应位置，确认开始验证?", "确认", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;

            Task.Run(() =>
            {
                try
                {
                    _stopVerifyMotion = false;
                    List<SemiPoint> rulerThenList = new List<SemiPoint>();
                    List<SemiPoint> rulerNowList = new List<SemiPoint>();

                    for (int i = 0; i < ModuleItem.RulerPoints.Count; i++)
                    {
                        if (_stopVerifyMotion)
                        {
                            _stopVerifyMotion = false;
                            return;
                        }

                        // TODO: 使用融合位置表计算期望坐标
                        SemiPoint rulerPoint = ModuleItem.RulerPoints[i]; // 暂时直接使用飞拍点

                        rulerThenList.Add(rulerPoint);

                        if (IsWaferCalib)
                            _fusionCalibMotionService.MoveWsAvoidance(rulerPoint.X, rulerPoint.Y);
                        else
                            _fusionCalibMotionService.MovePhsAvoidance(rulerPoint.X, rulerPoint.Y);

                        // TODO: 逼近识别，获取实际坐标
                        if (IsWaferCalib)
                        {
                            SemiPoint rulerNow = new SemiPoint(_hardware.Axis_X2.State.ActualPos, _hardware.Axis_Y1.State.ActualPos);
                            rulerNowList.Add(rulerNow);
                        }
                        else
                        {
                            SemiPoint rulerNow = new SemiPoint(_hardware.Axis_X1.State.ActualPos, _hardware.Axis_Y2.State.ActualPos);
                            rulerNowList.Add(rulerNow);
                        }
                    }

                    // TODO: 输出验证结果
                    // 对应旧项目: JM1Manager.Instance.pos_verify(filePath, rulerThenList, rulerNowList)

                    double totalError = 0;
                    for (int i = 0; i < rulerThenList.Count; i++)
                    {
                        double dx = rulerThenList[i].X - rulerNowList[i].X;
                        double dy = rulerThenList[i].Y - rulerNowList[i].Y;
                        totalError += Math.Sqrt(dx * dx + dy * dy);
                    }
                    double avgError = rulerThenList.Count > 0 ? totalError / rulerThenList.Count : 0;
                    MwMessageBox.Show($"验证完成！平均误差: {avgError:F4}mm");
                }
                catch (Exception ex) { MwMessageBox.Show($"验证失败：{ex.Message}"); }
            });
        }

        public void btnStopVerityWafer()
        {
            var result = MwMessageBox.Show("是否停止验证?", "确认停止", MessageBoxButton.YesNo);
            if (result == MessageBoxResult.Yes)
            {
                _stopVerifyMotion = true;
            }
        }

        #endregion

        #region 标定流程

        public async Task StartCalib()
        {
            if (IsCalibrating) return;
            IsCalibrating = true;
            IsProgressVisible = true;
            _cts = new CancellationTokenSource();

            try
            {
                if (PostProcessor != null)
                    await PostProcessor.ExecuteAsync(null, _cts.Token);
                MwMessageBox.Show("标定完成！");
            }
            catch (OperationCanceledException)
            {
                MwMessageBox.Show("标定已取消。");
            }
            catch (Exception ex)
            {
                MwMessageBox.Show($"标定失败：{ex.Message}");
            }
            finally
            {
                IsCalibrating = false;
                IsProgressVisible = false;
            }
        }

        public void btnStart() => _ = StartCalib();
        public void btnStop() => _cts?.Cancel();

        #endregion

        #region ROI

        private Rectangle1 GetRoiRect()
        {
            try
            {
                var region = CameraAxisViewModelSevice?.Regions;
                if (region?.Count > 0 && region[0].Region is RectRegion rect)
                {
                    return new Rectangle1
                    {
                        Start_X = rect.CenterPoint.Y - rect.Height / 2,
                        Start_Y = rect.CenterPoint.X - rect.Width / 2,
                        End_X = rect.CenterPoint.Y + rect.Height / 2,
                        End_Y = rect.CenterPoint.X + rect.Width / 2
                    };
                }
            }
            catch { }
            return null;
        }

        #endregion
        private async Task<bool> FindPointCircleAsync(CancellationToken token)
        {
            var roiRect = GetRoiRect();
            if (IsWaferCalib)
            {
                var request = new ApproachAlignmentRequest(
                axes: new[]
                {
                new ApproachAlignmentAxis(_hardware.Axis_X2.Name, 0.005),
                new ApproachAlignmentAxis(_hardware.Axis_Y1.Name, 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;
            }
            else
            {
                var request = new ApproachAlignmentRequest(
                axes: new[]
                {
                new ApproachAlignmentAxis(_hardware.Axis_X1.Name, 0.005),
                new ApproachAlignmentAxis(_hardware.Axis_Y2.Name, 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;
        }
        protected override void OnDeactivate()
        {
            UnsubscribeFromProgress();
            base.OnDeactivate();
        }
    }
}