using MainShell.Common;
using MainShell.Hardware;
using MainShell.Manual.Model;
using MainShell.Models;
using MainShell.Models.Wafer;
using MainShell.ParaSetting.Model;
using MainShell.Process;
using MainShell.ProcessResult;
using MainShell.Recipe.BaseBoard.Model;
using MainShell.Recipe.Models;
using MainShell.Resources.CustomControl;
using MaxwellFramework.Core.Interfaces;
using MwFramework.ManagerService;
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;

namespace MainShell.Manual.ViewModel
{
    public class DieBondingViewModel : OperateViewModelBase
    {
        private readonly RecipeManager _recipeManager;
        private readonly IEventAggregator _eventAggregator; // 引用 EventAggregator
        private readonly ProcessResultManager _processResultManager;
        private readonly HardwareManager _hardwareManager;
        private readonly IDieTransferPathGenerator _dieTransferPathGenerator;


        private List<DieTransferPathItem> _allDieTransferPathItems = new List<DieTransferPathItem>();

        private ObservableCollection<DieTransferPathItem> _dieTransferPathItems = new ObservableCollection<DieTransferPathItem>();
        /// <summary>
        /// 界面上显示的传输路径集合
        /// </summary>
        public ObservableCollection<DieTransferPathItem> DieTransferPathItems
        {
            get { return _dieTransferPathItems; }
            set { SetAndNotify(ref _dieTransferPathItems, value); }
        }

        private DieTransferPathItem _selectedDieTransferPathItem;
        public DieTransferPathItem SelectedDieTransferPathItem
        {
            get => _selectedDieTransferPathItem;
            set => SetAndNotify(ref _selectedDieTransferPathItem, value);
        }

        private readonly DieBondingManualSetting _dieBondingManualSetting;
        public DieBondingManualSysItem  DieBondingManualSysItem => _dieBondingManualSetting.DieBondingManualSysItem;
        public PaginationViewModel Pagination { get; } = new PaginationViewModel();
        public DieBondingViewModel(IEventAggregator eventAggregator, RecipeManager recipeManager,
            ProcessResultManager processResultManager, HardwareManager hardwareManager, IDieTransferPathGenerator dieTransferPathGenerator, IParameterManager parameterManager)
        {
            _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
            _recipeManager = recipeManager ?? throw new ArgumentNullException(nameof(recipeManager));
            _processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
            _hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager));
            _dieTransferPathGenerator = dieTransferPathGenerator ?? throw new ArgumentNullException(nameof(dieTransferPathGenerator));

            _cameraAxisViewModel = IoC.Get<Common.Display.ViewModel.CameraAxisViewModel>();
            _cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices;

            var _paramlist = parameterManager as IParamList;

            _dieBondingManualSetting = _paramlist.GetParameter<DieBondingManualSetting>();

            Pagination.PageChanged += (s, e) => LoadData();

            LoadData();
        }

        private void LoadData()
        {
            // 如果数据源为空，清空并返回
            if (_allDieTransferPathItems == null || !_allDieTransferPathItems.Any())
            {
                DieTransferPathItems = new ObservableCollection<DieTransferPathItem>();
                Pagination.TotalItems = 0;
                return;
            }

            // 1. 先更新总数（这很重要，因为TotalPages依赖它）
            Pagination.TotalItems = _allDieTransferPathItems.Count(); 
            
            // 2. 自动修正页码：如果当前页超过了新的总页数，强制跳到最后一页
            // 注意：修改 Pagination.CurrentPage 会再次触发 PageChanged -> LoadData，
            // 所以我们需要防止无限递归，或者只在必要时修正。
            // 在这里，简单的方式是计算 offset 时进行钳制，而不强行修改 CurrentPage 属性（取决于你的需求）
            // 或者更好的是：
            if (Pagination.CurrentPage > Pagination.TotalItems && Pagination.TotalItems > 0)
            {
                // 如果这里修改 CurrentPage 触发 LoadData，则本次 LoadData 可以直接中断
                Pagination.CurrentPage = Pagination.TotalPages; 
                return; 
            }

            // 3. 安全计算 Offset
            int safePage = Math.Min(Pagination.CurrentPage, Pagination.TotalPages);
            safePage = Math.Max(1, safePage); // 确保至少为1
            
            int offset = (safePage - 1) * Pagination.PageSize;
            int limit = Pagination.PageSize;

            // 4. 重置集合
            DieTransferPathItems = new ObservableCollection<DieTransferPathItem>(_allDieTransferPathItems.Skip(offset).Take(limit));
        }

        public async Task SaveDieBondingSetAsync()
        {
            bool success = await Loading.RunAsync(async (token, progress) =>
            {
                _dieBondingManualSetting.Write();

            }, "保存参数...",isIndeterminate:true,canCancel:false);
        }

        public Task GenerateTransPathAsync()
        {
            DieTransferPathRequest pathRequest = CreatePathRequest();
            DieTransferPathPlan pathPlan = _dieTransferPathGenerator.Generate(pathRequest);
            _allDieTransferPathItems = ConvertToPathItems(pathPlan);
            Pagination.CurrentPage = 1;
            LoadData();
            return Task.CompletedTask;
        }

        private DieTransferPathRequest CreatePathRequest()
        {
            DieTransferPathRequest pathRequest = new DieTransferPathRequest();
            pathRequest.DieRegion = DieBondingManualSysItem.DieRegion;
            pathRequest.SubstrateRegion = DieBondingManualSysItem.SubstrateRegion;
            pathRequest.TransPathType = DieBondingManualSysItem.TransPathType;
            pathRequest.PadRowDirectionStrategy = DieBondingManualSysItem.PadRowDirectionStrategy;
            pathRequest.DieRowDirectionStrategy = DieBondingManualSysItem.DieRowDirectionStrategy;
            pathRequest.SkipNgDie = true;
            pathRequest.DieCandidates = CreateDieCandidates(DieBondingManualSysItem.DieRegion);
            pathRequest.PadCandidates = CreatePadCandidates(DieBondingManualSysItem.SubstrateRegion);
            return pathRequest;
        }

        private List<Die> CreateDieCandidates(RegionModel region)
        {
            List<Die> dieCandidates = new List<Die>();
            if (region == null)
            {
                return dieCandidates;
            }

            for (int row = region.StartRow; row <= region.EndRow; row++)
            {
                for (int column = region.StartCol; column <= region.EndCol; column++)
                {
                    Die die = new Die();
                    die.Row = row;
                    die.Column = column;
                    die.X = column;
                    die.Y = row;
                    die.Status = DieStatus.Normal;
                    dieCandidates.Add(die);
                }
            }

            return dieCandidates;
        }

        private List<Pad> CreatePadCandidates(RegionModel region)
        {
            List<Pad> padCandidates = new List<Pad>();
            if (region == null)
            {
                return padCandidates;
            }

            for (int row = region.StartRow; row <= region.EndRow; row++)
            {
                for (int column = region.StartCol; column <= region.EndCol; column++)
                {
                    Pad pad = new Pad();
                    pad.Row = row;
                    pad.Column = column;
                    pad.X = column;
                    pad.Y = row;

                    SubstratePoint substratePoint;
                    if (TryGetSubstratePoint(row, column, out substratePoint))
                    {
                        pad.X = substratePoint.X;
                        pad.Y = substratePoint.Y;
                    }

                    padCandidates.Add(pad);
                }
            }

            return padCandidates;
        }

        private bool TryGetSubstratePoint(int row, int column, out SubstratePoint substratePoint)
        {
            substratePoint = default(SubstratePoint);

            SubstratePoint[,] substratePoints = _recipeManager.CurrentSubstrateRecipe != null
                ? _recipeManager.CurrentSubstrateRecipe.SubstratePoints
                : null;
            if (substratePoints == null)
            {
                return false;
            }

            int rowIndex = row - 1;
            int columnIndex = column - 1;
            if (rowIndex < 0 || rowIndex >= substratePoints.GetLength(0) || columnIndex < 0 || columnIndex >= substratePoints.GetLength(1))
            {
                return false;
            }

            substratePoint = substratePoints[rowIndex, columnIndex];
            return true;
        }

        private static List<DieTransferPathItem> ConvertToPathItems(DieTransferPathPlan pathPlan)
        {
            List<DieTransferPathItem> pathItems = new List<DieTransferPathItem>();
            if (pathPlan == null || pathPlan.Steps == null)
            {
                return pathItems;
            }

            foreach (DieTransferPathStep pathStep in pathPlan.Steps)
            {
                DieTransferPathItem pathItem = DieTransferPathItem.FromPathStep(pathStep);
                if (pathItem != null)
                {
                    pathItems.Add(pathItem);
                }
            }

            return pathItems;
        }
    }
}
