using JM1Vision;
using MainShell.AlgorithmCalib.Common;
using MainShell.AlgorithmCalib.Model;
using MainShell.Common;
using MainShell.Hardware;
using MainShell.Log;
using MainShell.Motion;
using MainShell.PageCalib.OriginCalib.Service;
using SemiconductorVisionAlgorithm.SemiCalib;
using SemiconductorVisionAlgorithm.SemiParams;
using SemiJM1Vision;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Point = SemiconductorVisionAlgorithm.SemiParams.Point;

namespace MainShell.AlgorithmCalib.Service
{
    /// <summary>
    /// 旋转表标定后处理器
    /// 对标原 RotateFormCalibTask 的逻辑
    /// </summary>
    public class RotateMatixFormCalibPostProcessor : IAlgorithmCalibrationPostProcessor
    {
        private readonly RotateMatixFormCalibMotionService _motionService;
        private readonly HardwareManager _hardware;
        private readonly RotateMatixFormCalibModuleItem _moduleItem;
        private readonly ApproachAlignmentService _approachAlignmentService;
        private readonly Func<Rectangle1> _roiRectProvider;  // ROI 提供者委托

        public event EventHandler<CalibrationProgressEventArgs> ProgressChanged;

        // 运行时数据
        private Point[,] _initialwsPos;
        private List<Point[,]> _calibWaferData = new List<Point[,]>();
        private List<double> _rotatePosList = new List<double>();
        private double _initialwsRotate;

        public string Name => "RotateFormCalib";

        public RotateMatixFormCalibPostProcessor(
            RotateMatixFormCalibMotionService motionService,
            HardwareManager hardware,
            RotateMatixFormCalibModuleItem moduleItem,
            ApproachAlignmentService approachAlignmentService,
            Func<Rectangle1> roiRectProvider)
        {
            _motionService = motionService ?? throw new ArgumentNullException(nameof(motionService));
            _hardware = hardware ?? throw new ArgumentNullException(nameof(hardware));
            _moduleItem = moduleItem ?? throw new ArgumentNullException(nameof(moduleItem));
            _approachAlignmentService = approachAlignmentService ?? throw new ArgumentNullException(nameof(approachAlignmentService));
            _roiRectProvider = roiRectProvider;
        }

        /// <summary>
        /// 标定主流程
        /// 对标原 RotateFormCalibTask.RotateCalib()
        /// </summary>
        public async Task ExecuteAsync(AlgorithmCalibExecutionResult calibrationResult, CancellationToken cancellationToken)
        {
            "旋转表标定开始。".LogInfo();

            try
            {
                // 清空历史数据
                _calibWaferData.Clear();
                _rotatePosList.Clear();

                double waferStep = _moduleItem.WaferStep;
                int rowCol = _moduleItem.RowCol;

                // 1. 移动到起始位置，采集初始网格点
                ReportProgress("采集初始网格点...", 0, 1);
                _initialwsPos = await GetInitPointsAsync(
                    waferStep,
                    _moduleItem.X1AvoidancePosition,
                    _moduleItem.StartY,
                    _moduleItem.StartX,
                    cancellationToken).ConfigureAwait(false);

                _initialwsRotate = _hardware.Axis_WS_R.State.ActualPos;
                string.Format("旋转表标定：初始旋转位置 = {0:F4}。", _initialwsRotate).LogInfo();

                // 2. 计算总旋转步数
                double rotateStep = _moduleItem.RotateStep;

                double negLimit = 0;
                double posLimit = 0;

                _hardware.Axis_WS_R.GetSoftMel(ref negLimit);
                _hardware.Axis_WS_R.GetSoftPel(ref posLimit);

                // 如果限位为0，使用默认范围
                if (negLimit == 0 && posLimit == 0)
                {
                    negLimit = -180;
                    posLimit = 180;
                    "旋转表标定：限位为0，使用默认范围 [-180, 180]。".LogInfo();
                }

                double startAngle = negLimit;
                double range = posLimit - startAngle;
                int totalCount = (int)(range / rotateStep) + 1;

                string.Format("旋转表标定：旋转步数 = {0}，范围 = [{1:F4}, {2:F4}]。", totalCount, negLimit, posLimit).LogInfo();

                // 初始化数据容器
                for (int i = 0; i < totalCount; i++)
                {
                    _rotatePosList.Add(0);
                    _calibWaferData.Add(new Point[rowCol, rowCol]);
                }

                // 3. 旋转轴先转到负限位
                ReportProgress("旋转轴移动到负限位...", 0, totalCount);
                await _motionService.RotatePosAsync(negLimit, cancellationToken).ConfigureAwait(false);

                // 4. 从负限位开始，逐步旋转到正限位，每步采集网格
                for (int stepIndex = 0; stepIndex < totalCount; stepIndex++)
                {
                    double targetRotate = startAngle + rotateStep * stepIndex;

                    if (targetRotate > posLimit)
                        break;

                    cancellationToken.ThrowIfCancellationRequested();

                    ReportProgress($"旋转到 {targetRotate:F2}°", stepIndex, totalCount);
                    // 旋转到目标角度
                    await _motionService.RotatePosAsync(targetRotate, cancellationToken).ConfigureAwait(false);
                    _rotatePosList[stepIndex] = _hardware.Axis_WS_R.State.ActualPos;


                    // 计算旋转后的拍照位置
                    var rotateOffset = targetRotate - _initialwsRotate;
                    var resultPts = new Point[rowCol, rowCol];
                    SemiJM1Manager.Instance.RotatePts("", _initialwsPos, rotateOffset, out resultPts);
                    ReportProgress($"采集网格点 ({stepIndex + 1}/{totalCount})", stepIndex + 1, totalCount);

                    var resultPoints = await GetApproachCenterPointsAsync(resultPts, stepIndex, cancellationToken).ConfigureAwait(false);
                    _calibWaferData[stepIndex] = resultPoints;
                }

                // 5. 融合计算
                ReportProgress("融合计算...", totalCount, totalCount);
                SemiJM1Manager.Instance.MakeRotateTable(
                    _calibWaferData, _rotatePosList, _moduleItem.RotateStep);

                // 6. 保存标定数据
                ReportProgress("保存标定数据...", totalCount, totalCount);
                string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CalibData");
                Directory.CreateDirectory(filePath);
                JM1Manager.Instance.Save(filePath);
                string.Format("旋转表标定：标定数据已保存到 {0}。", filePath).LogInfo();

                // 7. 保存调试数据
                string debugPath = Path.Combine(filePath, "RotateFormCalibDebug.csv");
                RotateMatixFormCalibFileService.SaveCalibrationGridData(debugPath, _calibWaferData, _rotatePosList);
                ReportProgress("标定完成", totalCount, totalCount);
                "旋转表标定完成。".LogInfo();
            }
            catch (OperationCanceledException)
            {
                "旋转表标定已取消。".LogInfo();
                throw;
            }
            catch (Exception ex)
            {
                string.Format("旋转表标定失败：{0}", ex.Message).LogSysError();
                throw;
            }
        }

        /// <summary>
        /// 验证流程
        /// 对标原 RotateFormCalibTask.RotateCalibVerify()
        /// </summary>
        public async Task VerifyAsync(CancellationToken cancellationToken)
        {
            "旋转表验证开始。".LogInfo();

            try
            {
                double verifyWaferStep = _moduleItem.VerifyWaferStep;
                double initWsRotate = _hardware.Axis_WS_R.State.ActualPos;
                double rotateOffset = _moduleItem.VerifyRotateRange;
                int totalSteps = _moduleItem.VerifyRowCol * _moduleItem.VerifyRowCol + 2;

                // 1. 获取验证初始点
                ReportProgress("获取验证初始点...", 0, totalSteps);
                var initVerifyPts = await GetInitListPointsAsync(
                    verifyWaferStep,
                    _moduleItem.VerifyStartX,
                    _moduleItem.VerifyStartY,
                    cancellationToken).ConfigureAwait(false);

                // 2. 旋转轴转到目标位置
                double targetRotate = initWsRotate + rotateOffset;
                ReportProgress("旋转到目标角度...", 1, totalSteps);
                await _motionService.RotatePosAsync(targetRotate, cancellationToken).ConfigureAwait(false);

                // 3. 调用算法接口计算预期位置
                ReportProgress("计算预期位置...", 2, totalSteps);
                var calPts = new List<Point>();
                SemiJM1Manager.Instance.GetRotateDstPos(initVerifyPts, initWsRotate, rotateOffset, out calPts);

                // 4. 逐个移动并采集实际位置
                ReportProgress("逐个采集实际位置...", 2, totalSteps);
                var approachPts = await MoveAndGetPtsAsync(calPts, cancellationToken).ConfigureAwait(false);

                // 5. 保存验证数据
                ReportProgress("保存验证数据...", totalSteps, totalSteps);
                string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RotateFormVerify.csv");
                RotateMatixFormCalibFileService.SaveVerifyPointsFile(filePath, calPts, approachPts);
                ReportProgress("验证完成", totalSteps, totalSteps);

                "旋转表验证完成。".LogInfo();
            }
            catch (OperationCanceledException)
            {
                "旋转表验证已取消。".LogInfo();
                throw;
            }
            catch (Exception ex)
            {
                string.Format("旋转表验证失败：{0}", ex.Message).LogSysError();
                throw;
            }
        }

        #region 辅助方法

        ///// <summary>
        ///// 蛇形扫描网格，返回 Point[RowCol, RowCol]
        ///// 对标原 RotateFormCalibTask.GetInitPoints()
        ///// </summary>
        //private async Task<Point[,]> GetInitPointsAsync(
        //    double waferStep, double x1, double y1, double x2,
        //    CancellationToken cancellationToken)
        //{
        //    int n = _moduleItem.RowCol;
        //    var pointArray = new Point[n, n];

        //    // 移动 X1 到避让位
        //    await _motionService.SafeMoveAsync(_hardware.Axis_PHS_X1, x1, cancellationToken).ConfigureAwait(false);

        //    for (int y = 0; y < n; y++)
        //    {
        //        for (int x = 0; x < n; x++)
        //        {
        //            int index = y % 2 == 0 ? x : n - 1 - x;
        //            double waferX = index * waferStep + x2;
        //            double waferY = y * waferStep + y1;

        //            cancellationToken.ThrowIfCancellationRequested();

        //            // 粗移到目标位置
        //            await _motionService.MoveWsAvoidanceAsync(waferX, waferY, cancellationToken).ConfigureAwait(false);

        //            // 逼近对齐
        //            bool success = await ApproachAtPointAsync(cancellationToken).ConfigureAwait(false);
        //            if (!success)
        //            {
        //                throw new InvalidOperationException(string.Format("逼近对齐失败 at ({0:F4}, {0:F4})。", waferX, waferY));
        //            }

        //            // 采集光栅尺位置
        //            var rulerX2 = _hardware.Axis_X2.State.ActualPos;
        //            var rulerY1 = _hardware.Axis_Y1.State.ActualPos;
        //            pointArray[y, index] = new Point(rulerX2, rulerY1);

        //            string.Format("初始网格点 [{0},{1}] = ({2:F4}, {3:F4})。", y, index, rulerX2,
        //    rulerY1).LogInfo();
        //        }
        //    }

        //    return pointArray;
        //}

        ///// <summary>
        ///// 根据旋转后的拍照位置，蛇形逐个对齐
        ///// 对标原 RotateFormCalibTask.GetApproachCenterPoints()
        ///// </summary>
        //private async Task<Point[,]> GetApproachCenterPointsAsync(
        //    Point[,] cameraPoints, int stepIndex,
        //    CancellationToken cancellationToken)
        //{
        //    int n = _moduleItem.RowCol;
        //    var resultArray = new Point[n, n];

        //    for (int y = 0; y < n; y++)
        //    {
        //        for (int x = 0; x < n; x++)
        //        {
        //            int index = y % 2 == 0 ? x : n - 1 - x;
        //            cancellationToken.ThrowIfCancellationRequested();

        //            double px = cameraPoints[y, index].X;
        //            double py = cameraPoints[y, index].Y;

        //            // 粗移到目标位置
        //            await _motionService.MoveWsAvoidanceAsync(px, py, cancellationToken).ConfigureAwait(false);

        //            // 逼近对齐
        //            bool success = await ApproachAtPointAsync(cancellationToken).ConfigureAwait(false);
        //            if (!success)
        //            {
        //                throw new InvalidOperationException(string.Format("逼近对齐失败 at ({0:F4}, {1:F4})。", px, py));
        //            }

        //            // 采集光栅尺位置
        //            var rulerX2 = _hardware.Axis_X2.State.ActualPos;
        //            var rulerY1 = _hardware.Axis_Y1.State.ActualPos;
        //            resultArray[y, index] = new Point(rulerX2, rulerY1);
        //        }
        //    }

        //    return resultArray;
        //}

        ///// <summary>
        ///// 蛇形扫描网格，返回 List&lt;Point&gt;
        ///// 对标原 RotateFormCalibTask.GetInitListPoints()
        ///// </summary>
        //private async Task<List<Point>> GetInitListPointsAsync(
        //    double waferStep, double x2, double y1,
        //    CancellationToken cancellationToken)
        //{
        //    int n = _moduleItem.VerifyRowCol;

        //    // 移动 X1 到避让位
        //    await _motionService.SafeMoveAsync(_hardware.Axis_PHS_X1, _moduleItem.X1AvoidancePosition, cancellationToken).ConfigureAwait(false);

        //    var pointArray = new List<Point>();

        //    for (int y = 0; y < n; y++)
        //    {
        //        for (int x = 0; x < n; x++)
        //        {
        //            int index = y % 2 == 0 ? x : n - 1 - x;
        //            double waferX = index * waferStep + x2;
        //            double waferY = y * waferStep + y1;

        //            cancellationToken.ThrowIfCancellationRequested();

        //            // 粗移到目标位置
        //            await _motionService.MoveWsAvoidanceAsync(waferX, waferY, cancellationToken).ConfigureAwait(false);

        //            // 逼近对齐
        //            bool success = await ApproachAtPointAsync(cancellationToken).ConfigureAwait(false);
        //            if (!success)
        //            {
        //                throw new InvalidOperationException(string.Format("逼近对齐失败 at ({0:F4},{1:F4})。", waferX, waferY));
        //            }

        //            // 采集光栅尺位置
        //            var rulerX2 = _hardware.Axis_X2.State.ActualPos;
        //            var rulerY1 = _hardware.Axis_Y1.State.ActualPos;
        //            pointArray.Add(new Point(rulerX2, rulerY1));
        //        }
        //    }

        //    return pointArray;
        //}

        ///// <summary>
        ///// 逐个移动到目标点并采集实际位置
        ///// 对标原 RotateFormCalibTask.MoveAndGetPts()
        ///// </summary>
        //private async Task<List<Point>> MoveAndGetPtsAsync(
        //    List<Point> targetPts,
        //    CancellationToken cancellationToken)
        //{
        //    var pointArray = new List<Point>();

        //    foreach (var pt in targetPts)
        //    {
        //        cancellationToken.ThrowIfCancellationRequested();

        //        // 粗移到目标位置
        //        await _motionService.MoveWsAvoidanceAsync(pt.X, pt.Y,
        //cancellationToken).ConfigureAwait(false);

        //        // 逼近对齐
        //        bool success = await ApproachAtPointAsync(cancellationToken).ConfigureAwait(false);
        //        if (!success)
        //        {
        //            throw new InvalidOperationException(string.Format("逼近对齐失败 at ({0:F4},{1:F4})。", pt.X, pt.Y));
        //        }

        //        // 采集光栅尺位置
        //        var rulerX2 = _hardware.Axis_X2.State.ActualPos;
        //        var rulerY1 = _hardware.Axis_Y1.State.ActualPos;
        //        pointArray.Add(new Point(rulerX2, rulerY1));
        //    }

        //    return pointArray;
        //}

        /// <summary>
        /// 移动逼近公共方法
        /// </summary>
        /// <param name="targetX"></param>
        /// <param name="targetY"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        private async Task<Point> MoveApproachAndCollectAsync(
      double targetX, double targetY, CancellationToken cancellationToken)
        {
            await _motionService.MoveWsAvoidanceAsync(targetX, targetY,
        cancellationToken).ConfigureAwait(false);

            bool success = await ApproachAtPointAsync(cancellationToken).ConfigureAwait(false);
            if (!success)
            {
                throw new InvalidOperationException($"逼近对齐失败 at ({targetX:F4}, {targetY:F4})。");
            }

            var rulerX2 = _hardware.Axis_X2.State.ActualPos;
            var rulerY1 = _hardware.Axis_Y1.State.ActualPos;
            return new Point(rulerX2, rulerY1);
        }


        /// <summary>
        /// 获取标定初始点组
        /// </summary>
        /// <param name="waferStep"></param>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<Point[,]> GetInitPointsAsync(
            double waferStep, double x1, double y1, double x2,
            CancellationToken cancellationToken)
        {
            int n = _moduleItem.RowCol;
            var pointArray = new Point[n, n];

            await _motionService.SafeMoveAsync(_hardware.Axis_PHS_X1, x1,
        cancellationToken).ConfigureAwait(false);

            for (int y = 0; y < n; y++)
            {
                for (int x = 0; x < n; x++)
                {
                    int index = y % 2 == 0 ? x : n - 1 - x;
                    double waferX = index * waferStep + x2;
                    double waferY = y * waferStep + y1;

                    cancellationToken.ThrowIfCancellationRequested();

                    pointArray[y, index] = await MoveApproachAndCollectAsync(
                        waferX, waferY, cancellationToken).ConfigureAwait(false);

                    string.Format("初始网格点 [{0},{1}] = ({2:F4}, {3:F4})。",
                        y, index, pointArray[y, index].X, pointArray[y, index].Y).LogInfo();
                }
            }

            return pointArray;
        }

        /// <summary>
        /// 标定流程内获取点
        /// </summary>
        /// <param name="cameraPoints"></param>
        /// <param name="stepIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<Point[,]> GetApproachCenterPointsAsync(
            Point[,] cameraPoints, int stepIndex,
            CancellationToken cancellationToken)
        {
            int n = _moduleItem.RowCol;
            var resultArray = new Point[n, n];

            for (int y = 0; y < n; y++)
            {
                for (int x = 0; x < n; x++)
                {
                    int index = y % 2 == 0 ? x : n - 1 - x;
                    cancellationToken.ThrowIfCancellationRequested();

                    resultArray[y, index] = await MoveApproachAndCollectAsync(
                        cameraPoints[y, index].X, cameraPoints[y, index].Y,
                        cancellationToken).ConfigureAwait(false);
                }
            }

            return resultArray;
        }

        /// <summary>
        /// 验证流程获取初始点
        /// </summary>
        /// <param name="waferStep"></param>
        /// <param name="x2"></param>
        /// <param name="y1"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<List<Point>> GetInitListPointsAsync(
            double waferStep, double x2, double y1,
            CancellationToken cancellationToken)
        {
            int n = _moduleItem.VerifyRowCol;
            await _motionService.SafeMoveAsync(_hardware.Axis_PHS_X1, _moduleItem.X1AvoidancePosition,
        cancellationToken).ConfigureAwait(false);

            var pointArray = new List<Point>();

            for (int y = 0; y < n; y++)
            {
                for (int x = 0; x < n; x++)
                {
                    int index = y % 2 == 0 ? x : n - 1 - x;
                    double waferX = index * waferStep + x2;
                    double waferY = y * waferStep + y1;

                    cancellationToken.ThrowIfCancellationRequested();

                    pointArray.Add(await MoveApproachAndCollectAsync(
                        waferX, waferY, cancellationToken).ConfigureAwait(false));
                }
            }

            return pointArray;
        }

        /// <summary>
        /// 验证流程获取旋转后验证点
        /// </summary>
        /// <param name="targetPts"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<List<Point>> MoveAndGetPtsAsync(
            List<Point> targetPts,
            CancellationToken cancellationToken)
        {
            var pointArray = new List<Point>();

            foreach (var pt in targetPts)
            {
                cancellationToken.ThrowIfCancellationRequested();

                pointArray.Add(await MoveApproachAndCollectAsync(
                    pt.X, pt.Y, cancellationToken).ConfigureAwait(false));
            }

            return pointArray;
        }

        /// <summary>
        /// 逼近对齐
        /// </summary>
        private async Task<bool> ApproachAtPointAsync(CancellationToken cancellationToken)
        {
            Rectangle1 roiRect = _roiRectProvider?.Invoke();
            var request = new ApproachAlignmentRequest(
                axes: new[]
                {
                      new ApproachAlignmentAxis("X2轴",  _moduleItem.AlignTolerance),
                      new ApproachAlignmentAxis("Y1轴",  _moduleItem.AlignTolerance)
                },
                camera: CameraType.TopPositionCamera)
            {
                MaxIterations = 3,
                RecognitionTimeoutMilliseconds = 5000,
                RecognitionParameters = new CenterRecognitionParameters()
                {
                    Type = CenterRecognitionType.EdgeCircle,
                    rectangle = roiRect
                }
            };

            var result = await _approachAlignmentService.ApproachAlignmentAsync(request, cancellationToken).ConfigureAwait(false);
            return result.Succeeded;
        }


        private void ReportProgress(string message, int current, int total)
        {
            ProgressChanged?.Invoke(this, new CalibrationProgressEventArgs
            {
                Message = message,
                Current = current,
                Total = total
            });
        }
        #endregion
    }
}