using Admin.Core.Common;
using Admin.Core.IService;
using Admin.Core.Model;
using Admin.Core.Model.Model_New;
using Aucma.Core.PrintTo.Common;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using FastReport;
using log4net;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace Aucma.Core.PrintTo.ViewModels
{
    public partial class PrintToDevViewModel : ObservableObject
    {
        private static readonly log4net.ILog log = LogManager.GetLogger(typeof(PrintToDevViewModel));

        protected readonly IOrderBomInfoServices  _orderBomInfoServices;
        protected readonly IPrintBarCodeServices  _printBarCodeServices;
        protected readonly IBaseBomInfoServices _baseBomInfoServices;
        static List<BaseBomInfo> tmpList = new List<BaseBomInfo>();

        private List<BaseBomInfo> items { get; }
        private Queue<BaseBomInfo> BarcodesUnprinted { get; } = new Queue<BaseBomInfo>();
        private Queue<BaseBomInfo> BarcodesPrinted { get; } = new Queue<BaseBomInfo>();
        private PrintState printState { get; set; } = PrintState.Idle;//打印状态
        protected bool isPrint { get; set; } = true;//打印标志
        public int _printType { get; set; }//打印类型
        #region 构造函数
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="productCode">产品编码</param>
        /// <param name="materialCode">物料编码</param>
        /// <param name="materialName">型号简码</param>
        /// <param name="printAmount">打印数量</param>
        public PrintToDevViewModel(string order_code,string productCode, string productName, int printAmount,string printName,int printType)
        {
            _orderBomInfoServices = App.ServiceProvider.GetService<IOrderBomInfoServices>();
            _printBarCodeServices = App.ServiceProvider.GetService<IPrintBarCodeServices>();
            _baseBomInfoServices = App.ServiceProvider.GetService<IBaseBomInfoServices>();

            _orderCode = order_code;
            ProductCode = productCode;
            //MaterialName = materialName;
            //MaterialCode= materialCode;
            PrintAmount = printAmount;
            PrintName = printName;
            Progress = 0;
            MaxProgress = printAmount;//最大数
            State = "Green";
            ErrorNum = 0;//异常
            printState = PrintState.Printing;
            SuspendEnabled = "False";//暂停打印
            OperateEnabled = "True";//打印
            _printType = printType;
            // 非阻塞打印
            Task.Run(async () =>
            {
                await ExecPrintAsync(productCode, printType, printAmount);
            });
        }
        #endregion

        #region 选中订单参数

        #region 订单编码
        private string _orderCode;

        public string OrderCode { get => _orderCode; set => SetProperty(ref _orderCode, value); }
        #endregion

        #region 订单编码
        private string _orderNo;

        public string OrderNo { get => _orderNo; set => SetProperty(ref _orderNo, value); }
        #endregion

        #region 打印名称
        private string _printName;

        public string PrintName { 
            get => _printName; 
            set => SetProperty(ref _printName, value);
        }
        #endregion

        #region 产品编码
        private string _productCode;

        public string ProductCode { get => _productCode; set => SetProperty(ref _productCode, value); }
        #endregion

        #region 型号简码
        private string _materialName;

        public string MaterialName { get => _materialName; set => SetProperty(ref _materialName, value); }
        #endregion

        #region 物料编码
        private string _materialCode;

        public string MaterialCode { get => _materialCode; set => SetProperty(ref _materialCode, value); }
        #endregion

        #region 打印数量
        private int _printAmount;

        public int PrintAmount { get => _printAmount; set => SetProperty(ref _printAmount, value); }
        #endregion

        #region 异常数量
        private int _errorNum;

        public int ErrorNum { get => _errorNum; set => SetProperty(ref _errorNum, value); }
        #endregion

        #region 打印进度
        private string _printProgress;

        public string PrintProgress { get => _printProgress; set => SetProperty(ref _printProgress, value); }
        #endregion

        #region 进度条最大值
        private int _maxProgress;

        public int MaxProgress { get => _maxProgress; set => SetProperty(ref _maxProgress, value); }
        #endregion

        #region 进度条进度
        private int _progress;

        public int Progress { get => _progress; set => SetProperty(ref _progress, value); }
        #endregion

        #region 打印状态
        private string _state;

        public string State { get => _state; set => SetProperty(ref _state, value); }
        #endregion

        #region 开启、暂停状态按钮 名称
        private string _stopOrStart;

        public string StopOrStart { get => _stopOrStart; set => SetProperty(ref _stopOrStart, value); }
        #endregion

        #region 操作打印按钮状态
        private string _operateEnabled;
        public string OperateEnabled
        {
            get => _operateEnabled;
            set => SetProperty(ref _operateEnabled, value);
        }
        #endregion

        #region 操作暂停按钮状态
        private string _suspendEnabled;
        public string SuspendEnabled
        {
            get => _suspendEnabled;
            set => SetProperty(ref _suspendEnabled, value);
        }
        #endregion

     

        #endregion

        #region 打印操作

        [RelayCommand]
        public void StartOperate()
        {
            if (string.IsNullOrEmpty(PrintName))
            {
                MessageBox.Show("打印名称不可为空?", "系统提醒", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.No);
                return;
            }
            printState = PrintState.Printing;
            SuspendEnabled = "True";
            OperateEnabled = "False";
            State = "Green";
            if (isPrint)//首次打印
            {
                isPrint = false;
                // 非阻塞打印
                Task.Run(async () =>
                {
                    await Print();
                });
            }
        }

        #region 暂停
        [RelayCommand]
        public void SuspendOperate()
        {
            if (MessageBox.Show("确定要暂停打印吗?", "系统提醒", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
            {
                isPrint = false;
                printState = PrintState.Paused;
            }
        }
        #endregion

        #region 关闭当前界面
        /// <summary>
        /// 关闭当前界面
        /// </summary>
        /// <param name="parameter"></param>
        [RelayCommand]
        public void CloseWindow(object parameter)
        {
            var window = parameter as Window;
            if (window == null) return;
            isPrint = true;
            if (printState == PrintState.Completetd)
            {
                WeakReferenceMessenger.Default.Send<string>("Refresh");//刷新窗口
                window.Close();
                return;
            }
            if (MessageBox.Show("确定要退出打印吗?", "系统提醒", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
            {
                printState = PrintState.Stopped;
                WeakReferenceMessenger.Default.Send<string>("Refresh");//刷新窗口
                window.Close();
            }
        }

        #endregion

        #endregion

        #region 将打印数据添加到队列中
        /// <summary>
        /// 将打印数据添加到队列中
        /// </summary>
        /// <param name="orderNo">订单号</param>
        /// <param name="materialCode">物料码</param>
        /// <param name="planAmount">打印数量</param>
        public async Task ExecPrintAsync(string productCode, int printType, int planAmount)
        {
            tmpList.Clear();
            BaseBomInfo baseBomInfo = null;
            List<BaseBomInfo> orderBomInfoList = await _baseBomInfoServices.QueryAsync();
            if (printType==1)//箱壳
            {
                GetParentID(orderBomInfoList, productCode);
                //OrderBomInfo obj = await _orderBomInfoServices.FirstAsync(d => d.MaterialCode == materialCode);
                if (tmpList.Count() == 0)
                {
                    MessageBox.Show("无法查询打印条码数据", "系统提醒");
                    return;
                }
                baseBomInfo= tmpList.FirstOrDefault(d=>d.MaterialType=="200");
            }
            if (printType == 2)//内胆
            {
                GetParentID(orderBomInfoList, productCode);
               
                if (tmpList.Count() == 0)
                {
                    MessageBox.Show("无法查询打印条码数据,数据为空!", "系统提醒");
                    return;
                }
                baseBomInfo = tmpList.FirstOrDefault(d => d.MaterialType == "500");
            }

            if (baseBomInfo == null)
            {
                MessageBox.Show("无法查询打印条码数据,数据为空", "系统提醒");
                return;
            }
            for (int i = 0; i < planAmount; i++) { BarcodesUnprinted.Enqueue(baseBomInfo); }
        }
        #endregion

        #region 打印
        
        public async Task<bool> Print()
        {
            try
            {
                string printer = Appsettings.app("Printer", "PrinterName");
                int i = 1;
                while (BarcodesUnprinted.Count > 0)
                {
                    if (printState == PrintState.Paused)
                    {
                        SetPaused();
                        continue;
                    }
                    if (printState == PrintState.Completetd) break;
                    PrintBarCode printBarCode = new PrintBarCode();
                    try
                    {
                        var item = BarcodesUnprinted.Peek();
                        string barCode = string.Empty;
                        if (_printType== 500)
                        {
                            string rowNum = await GetMaxNumAsync(item.MaterialCode,"B");//最大值+1
                            barCode = $"B{DateTime.Now.ToString("yyMMdd")}{item.MaterialCode}{rowNum}";
                            PrintProgress = $"[{PrintAmount}/{i}]  {barCode}";
                            printBarCode.MaterialBarcode = barCode;
                            printBarCode.PrintBarType = 1;
                            Console.WriteLine($"B{DateTime.Now.ToString("yyMMdd")}{item.MaterialCode}{rowNum}");
                        }
                        if (_printType == 200)
                        {
                            string rowNum = await GetMaxNumAsync(item.MaterialCode, "L");//最大值+1
                            barCode = $"L{DateTime.Now.ToString("yyMMdd")}{item.MaterialCode}{rowNum}";
                            PrintProgress = $"[{PrintAmount}/{i}]  {barCode}";
                            printBarCode.MaterialBarcode = barCode;
                            printBarCode.PrintBarType = 2;//内胆码
                            Console.WriteLine($"L{DateTime.Now.ToString("yyMMdd")}{item.MaterialCode}{rowNum}");
                        }
                        #region 打印

                        //对接打印机
                        Report barReport = new Report();
                        barReport.Load(System.Environment.CurrentDirectory + @"\Report\MaterialBar.frx");//打印报表位置

                        // 设置打印机和打印选项
                        barReport.PrintSettings.ShowDialog = false; // 是否打开打印机选择框  
                        barReport.PrintSettings.Printer = printer; // 设置打印机名称
                        barReport.PrintSettings.Copies = 1; // 设置打印份数
                                                            //barReport.PrintSettings.PageRange = "1-3"; // 设置打印页范围
                        
                        barReport.SetParameterValue("BoxBarData.Id", barCode);
                        barReport.SetParameterValue("BoxBarData.Order_No", _orderCode);//订单号
                        barReport.SetParameterValue("BoxBarData.Order_Material_Name", PrintName);//物料简码
                        barReport.SetParameterValue("BoxBarData.Bar_Code", barCode);//二维码

                        //barReport.Prepare();
                        //string BarPath = System.Environment.CurrentDirectory + @"\pdf\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";
                        //barReport.Export(new PDFExport(), BarPath);

                        barReport.Print();

                        #endregion

                        printBarCode.OrderCode = ProductCode;
                        printBarCode.MaterialCode = item.MaterialCode;
                        printBarCode.MaterialName = item.MaterialName;
                        printBarCode.PrintTime = DateTime.Now;
                        printBarCode.SupplementMaterial =0;
                        if (string.IsNullOrEmpty(printBarCode.MaterialBarcode))
                        {
                            throw new Exception("条码生成异常");//抛出异常,回滚事务,事务退出
                        }
                        var num= await _printBarCodeServices.AddAsync(printBarCode);
                        if (num<=0)
                        {
                            ErrorNum++; 
                            log.Error($"打印保存出错:{printBarCode.ToJson()}");
                        }
                        BarcodesPrinted.Enqueue(BarcodesUnprinted.Dequeue());
                        Thread.Sleep(1000);
                    }
                    catch (Exception ex)
                    {
                        log.Error($"打印出错:{ex.Message}\n{printBarCode.ToJson()}");
                        ErrorNum++;
                        
                    }
                    Progress = i;
                    i++;
                }
                //打印完成
                SetCompletetd();
                return  await Task.FromResult(true);
            }
            catch (Exception ex)
            {
                log.Error($"打印出错:{ex.Message}");
                return await Task.FromResult(false);
            }
            finally
            {
                isPrint = true;
            }
        }

        #region 获取最大值
        /// <summary>
        /// 获取最大值
        /// </summary>
        /// <param name="MaterialCode"></param>
        /// <returns></returns>
        public async Task<string> GetMaxNumAsync(string MaterialCode,string falg)
        {
            try
            {
                List<int> tempList = new List<int>();
                var list = await _printBarCodeServices.QueryAsync(d => d.MaterialBarcode.Contains(MaterialCode) && d.MaterialBarcode.Substring(0, 1).Equals(falg));
                if (list.Count() == 0)
                {
                    return "0001";
                }
                list.ForEach(item =>
                {
                    int num = Convert.ToInt32(item.MaterialBarcode.Substring(item.MaterialBarcode.Length - 1, 4));
                    tempList.Add(num);
                });
                string maxStr = (tempList.Max() + 1).ToString();
                string rowNum = maxStr.PadLeft(4, '0');
                return rowNum;
            }
            catch
            {
                return "0001";
            }
        }
        #endregion

        #endregion

        #region 暂停
        /// <summary>
        /// 暂停
        /// </summary>
        private void SetPaused()
        {
            printState = PrintState.Paused;

            State = "yellow";
            isPrint = false;

            SuspendEnabled = "False";
            OperateEnabled = "True";
        }
        #endregion

        #region 完成
        /// <summary>
        /// 暂停
        /// </summary>
        private void SetCompletetd()
        {
            printState = PrintState.Completetd;

            State = "Green";
            StopOrStart = "已完成";
            isPrint = false;
            OperateEnabled = "True";
        }
        #endregion


        #region 递归
        public static void GetParentID(List<BaseBomInfo> treeNodes, string materialCode)
        {
            if (string.IsNullOrEmpty(materialCode))
            {
                return;
            }
            var query = from c in treeNodes
                        where c.ParentId == materialCode
                        select c;
            foreach (var item in query)
            {
                GetParentID(treeNodes, item.MaterialCode);
                tmpList.Add(item);
            }
        }

        #endregion
    }
}