using PTMedicalInsurance.Variables;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PTMedicalInsurance.Common
{
    public class ProgressDialog : Form
    {
        private ProgressBar progressBar1;
        private Label labelStatus;
        private Button cancelButton;
        BackgroundWorker _backgroundWorker;
        private int maximum;

        public ProgressDialog()
        {
            Init();
        }

        public ProgressDialog(BackgroundWorker backgroundWorker)
        {
            Init();
            _backgroundWorker = backgroundWorker;
        }

        private void  Init()
        {
            Application.EnableVisualStyles();
            this.Text = "正在查询...";
            this.StartPosition = FormStartPosition.CenterParent;
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.ShowInTaskbar = false;
            this.TopMost = true; // 确保进度条始终在最前面
            this.CenterToScreen();

            progressBar1 = new ProgressBar
            {
                Location = new System.Drawing.Point(12, 12),
                Size = new System.Drawing.Size(260, 23)
            };
            progressBar1.Style = ProgressBarStyle.Continuous;
            //progressBar1.Style = ProgressBarStyle.Marquee;
            //progressBar1.MarqueeAnimationSpeed = 50;
            Controls.Add(progressBar1);

            labelStatus = new Label
            {
                Location = new System.Drawing.Point(12, 41),
                Size = new System.Drawing.Size(260, 23)
            };
            Controls.Add(labelStatus);

            //// 初始化取消按钮
            //cancelButton = new Button
            //{
            //    Text = "取消",
            //    Location = new System.Drawing.Point(197, 41), // 设置适当的位置
            //    Size = new System.Drawing.Size(75, 23) // 设置按钮大小
            //};
            //cancelButton.Click += CancelButton_Click; // 添加点击事件处理程序
            //Controls.Add(cancelButton);


            // 初始化取消按钮
            cancelButton = new Button
            {
                Text = "取消",
                Location = new System.Drawing.Point(197, 60), // 修改Y坐标以避免与labelStatus重叠
                Size = new System.Drawing.Size(75, 23) // 设置按钮大小
            };
            cancelButton.Click += CancelButton_Click; // 添加点击事件处理程序
            Controls.Add(cancelButton);

            // 设置默认样式
            SetStyle(ControlStyles.ResizeRedraw, true);
            ClientSize = new System.Drawing.Size(284, 100);
        }

        // 允许外部设置进度条的值
        public int ProgressValue
        {
            set { if (InvokeRequired) Invoke(new Action(() => progressBar1.Value = value)); else progressBar1.Value = value; }
        }

        public void UpdateProgress(int progress)
        {
            //if (progressBar1.InvokeRequired)
            //{
            //    progressBar1.Invoke(new Action<int>(UpdateProgress), progress);
            //}
            //else
            //{
            //    progressBar1.Value = progress;
            //    //这个有点糊涂了，这个进度条显示总是少一个
            //    labelStatus.Text = $"已完成 {progress}/{maximum}";
            //}
            this.Invoke((MethodInvoker)delegate 
            {
                progressBar1.Value = progress;
                //这个有点糊涂了，这个进度条显示总是少一个
                labelStatus.Text = $"已完成 {progress}/{maximum}";

                ///在Windows Forms应用程序中，控件的更新通常是由操作系统消息循环处理的。当你修改一个控件的属性（如 Text 或 Value），
                ///这些更改并不会立即反映在界面上，而是会被放入队列等待下一个合适的时机进行绘制。这是因为直接更新控件属性并不会强制执行重绘操作，
                ///系统可能会批量处理多个更新以提高效率。
                ///使用 Refresh() 方法 调用控件的 Refresh() 方法会强制该控件立即重绘自身。这包括清除控件并重新绘制其所有内容
                if (progress == maximum)
                {
                    progressBar1.Refresh();
                    labelStatus.Refresh();
                }
                
            });  
        }

        public void SetProgress(int max)
        {
            maximum = max;
            progressBar1.Maximum = maximum;
        }

        // 允许外部设置状态文本
        public string StatusText
        {
            set { if (InvokeRequired) Invoke(new Action(() => labelStatus.Text = value)); else labelStatus.Text = value; }
        }

        //异步展示
        public async void ShowAsync()
        {
            await Task.Run(() => progressBar1.Show());
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            // 这里可以放置取消操作的逻辑
            // 比如通知BackgroundWorker取消工作
            if (_backgroundWorker != null && _backgroundWorker.WorkerSupportsCancellation)
            {
                _backgroundWorker.CancelAsync();
            }
            this.Close(); // 关闭对话框
        }
    }
    public class DataLoader : IDisposable
    {
        private  BackgroundWorker _backgroundWorker = new BackgroundWorker();
        public delegate int MyFunc<T1>(out T1 err,ProgressCallback progressCallback);
        private MyFunc<string> _queryExportDataAction;
        private ProgressDialog progressDialog ;
        private Form mainForm;

        // 定义进度回调委托
        public delegate void ProgressCallback(int progress);

        public DataLoader(MyFunc<string> queryExportDataAction,Form frm)
        {
            mainForm = frm;
            _queryExportDataAction = queryExportDataAction ?? throw new ArgumentNullException(nameof(queryExportDataAction));
            
            // 配置 BackgroundWorker
            _backgroundWorker.WorkerReportsProgress = true;
            _backgroundWorker.WorkerSupportsCancellation = true;
            _backgroundWorker.DoWork += BackgroundWorker_DoWork;
            _backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
            _backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
        }

        public void StartQueryExportData(int total, Action<int, string> onCompleted)
        {
            progressDialog = new ProgressDialog(_backgroundWorker);
            if (mainForm == null)
            {
                progressDialog.Show();
            }
            else
            {
                progressDialog.Show(mainForm);
            }
            if (_backgroundWorker.IsBusy) return;

            this._onCompleted = onCompleted;

            _backgroundWorker.RunWorkerAsync(total);
        }

        private Action<int, string> _onCompleted;

        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // 调用传入的方法
            string errMsg = "";
            int total = (int)e.Argument; // 获取传入的总项目数
            progressDialog.SetProgress(total);
            //注意，如果_queryExportDataAction 事件里需要更新UI 必须使用 Control.Invoke 或 Control.BeginInvoke。否则会导致程序卡死
            ///类似这样:this.Invoke((MethodInvoker)delegate {labelProgress.Text = $"Progress: {progress}%"; });
            int result = _queryExportDataAction(out errMsg, (progress) =>
            {
                if (!_backgroundWorker.CancellationPending)
                {
                    _backgroundWorker.ReportProgress(progress);
                }
                else
                {
                    // 如果用户请求了取消，则跳出循环或采取其他措施
                    // 这个异常处理查询下
                    throw new OperationCanceledException();
                }
            });
            e.Result = Tuple.Create(result, errMsg);
        }

        private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!_backgroundWorker.CancellationPending)
            {
                System.Threading.Thread.Sleep(1000);
            }
            
            progressDialog.Close();
            if (e.Error != null)
            {
                // 处理错误
                MessageBox.Show($"An error occurred: {e.Error.Message}");
            }
            else if (e.Cancelled)
            {
                // 处理取消的情况
                MessageBox.Show("Operation was cancelled.");
            }
            else
            {

                var resultTuple = (Tuple<int, string>)e.Result;
                int result = resultTuple.Item1;
                string errMsg = resultTuple.Item2;

                // 调用回调函数，传递结果和错误信息
                _onCompleted?.Invoke(result, errMsg);
            }

            Dispose();
        }

        private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressDialog.UpdateProgress(e.ProgressPercentage );
        }

        public void Dispose()
        {
            _backgroundWorker.Dispose();
            progressDialog.Dispose();
        }
    }

}
