using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models.Dtos;
using Elwig.Models.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Elwig.Windows {
    public partial class MailWindow : ContextWindow {

        // used for document sorting while generating!
        public enum DocType { Undefined, Custom, MemberDataSheet, DeliveryConfirmation, CreditNote }

        public class SelectedDoc(DocType type, string name, object? details = null) {
            public DocType Type = type;
            public string Name { get; set; } = name;
            public object? Details = details;
        }

        public class GeneratedDoc {
            public DocType Type;
            public Document Doc;

            public GeneratedDoc(string pdfPath) {
                Type = DocType.Custom;
                Doc = Document.FromPdf(pdfPath);
            }

            public GeneratedDoc(Document doc) {
                Type = doc is MemberDataSheet ? DocType.MemberDataSheet :
                    doc is DeliveryConfirmation ? DocType.DeliveryConfirmation :
                    doc is CreditNote ? DocType.CreditNote : DocType.Undefined;
                Doc = doc;
            }
        }

        public static readonly string[] AvaiableDocuments = [
            MemberDataSheet.Name,
            DeliveryConfirmation.Name,
            CreditNote.Name,
        ];

        protected Season? Season;
        public ObservableCollection<SelectedDoc> SelectedDocs = [];
        public IEnumerable<Member> Recipients = [];

        protected Document? PrintDocument;
        protected Dictionary<Member, List<Document>>? EmailDocuments;

        public static readonly DependencyProperty PostalAllCountProperty = DependencyProperty.Register("PostalAllCount", typeof(int), typeof(MailWindow));
        public int PostalAllCount {
            get => (int)GetValue(PostalAllCountProperty);
            private set => SetValue(PostalAllCountProperty, value);
        }

        public static readonly DependencyProperty PostalWishCountProperty = DependencyProperty.Register("PostalWishCount", typeof(int), typeof(MailWindow));
        public int PostalWishCount {
            get => (int)GetValue(PostalWishCountProperty);
            private set => SetValue(PostalWishCountProperty, value);
        }

        public static readonly DependencyProperty PostalNoEmailCountProperty = DependencyProperty.Register("PostalNoEmailCount", typeof(int), typeof(MailWindow));
        public int PostalNoEmailCount {
            get => (int)GetValue(PostalNoEmailCountProperty);
            private set => SetValue(PostalNoEmailCountProperty, value);
        }

        public static readonly DependencyProperty EmailAllCountProperty = DependencyProperty.Register("EmailAllCount", typeof(int), typeof(MailWindow));
        public int EmailAllCount {
            get => (int)GetValue(EmailAllCountProperty);
            private set => SetValue(EmailAllCountProperty, value);
        }

        public static readonly DependencyProperty EmailWishCountProperty = DependencyProperty.Register("EmailWishCount", typeof(int), typeof(MailWindow));
        public int EmailWishCount {
            get => (int)GetValue(EmailWishCountProperty);
            private set => SetValue(EmailWishCountProperty, value);
        }

        private ICommand _deleteCommand;
        public ICommand DeleteCommand => _deleteCommand ??= new ActionCommand(() => {
            var idx = SelectedDocumentsList.SelectedIndex;
            if (idx == -1)
                return;
            SelectedDocs.RemoveAt(SelectedDocumentsList.SelectedIndex);
            SelectedDocumentsList.SelectedIndex = idx < SelectedDocumentsList.Items.Count ? idx : idx - 1;
        });

        // powershell -Command "$(Get-WmiObject -Class Win32_Printer | Where-Object {$_.Default -eq $True}).Name"
        public MailWindow() {
            InitializeComponent();
            AvaiableDocumentsList.ItemsSource = AvaiableDocuments;
            SelectedDocumentsList.ItemsSource = SelectedDocs;

            DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
            DocumentFooterLabel.Visibility = Visibility.Hidden;
            DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
            CreditNoteFooterInput.Visibility = Visibility.Hidden;
            RecipientsActiveMembersInput.IsChecked = true;

            DeliveryConfirmationFooterInput.Text = App.Client.TextDeliveryConfirmation;
            CreditNoteFooterInput.Text = App.Client.TextCreditNote;

            PostalSender1.Text = App.Client.Sender1;
            PostalSender2.Text = App.Client.Sender2;
            EmailSubjectInput.Text = App.Client.TextEmailSubject ?? "Rundschreiben";
            EmailBodyInput.Text = App.Client.TextEmailBody ?? "Sehr geehrtes Mitglied,\n\nim Anhang finden Sie das aktuelle Rundschreiben.\n\nIhre Winzergenossenschaft\n";
        }

        protected override async Task OnRenewContext() {
            Season = await Context.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync();
            var l = new List<string> {
                MemberDataSheet.Name
            };
            if (Season != null) {
                l.Add($"{DeliveryConfirmation.Name} {Season.Year}");
                l.AddRange(Season.PaymentVariants.Where(v => !v.TestVariant).OrderBy(v => v.AvNr).Select(v => $"{CreditNote.Name} – {v.Name}"));
            }
            AvaiableDocumentsList.ItemsSource = l;

            ControlUtils.RenewItemsSource(MemberBranchInput, await Context.Branches
                .Where(b => b.Members.Any())
                .OrderBy(b => b.Name)
                .ToListAsync(), b => (b as Branch)?.ZwstId);
            if (MemberBranchInput.SelectedItems.Count == 0) MemberBranchInput.SelectAll();
            ControlUtils.RenewItemsSource(MemberKgInput, await Context.Katastralgemeinden
                .Where(k => k.WbKg.Members.Any())
                .OrderBy(k => k.Name)
                .ToListAsync(), k => (k as AT_Kg)?.KgNr);
            if (MemberKgInput.SelectedItems.Count == 0) MemberKgInput.SelectAll();
            ControlUtils.RenewItemsSource(MemberAreaComInput, await Context.AreaCommitmentTypes
                .OrderBy(a => a.VtrgId)
                .ToListAsync(), a => (a as AreaComType)?.VtrgId);
            if (MemberAreaComInput.SelectedItems.Count == 0) MemberAreaComInput.SelectAll();
            ControlUtils.RenewItemsSource(MemberCustomInput, await Context.Members
                .Where(m => m.IsActive)
                .OrderBy(m => m.FamilyName)
                .ThenBy(m => m.GivenName)
                .ToListAsync(), m => (m as Member)?.MgNr);
            if (MemberCustomInput.SelectedItems.Count == 0) MemberCustomInput.SelectAll();

            await UpdateRecipients();
        }

        private void ContinueButton_Click(object sender, RoutedEventArgs evt) {
            TabControl.SelectedIndex = 1;
            TabControl.AllowDrop = false;
        }

        private void BackButton_Click(object sender, RoutedEventArgs evt) {
            TabControl.SelectedIndex = 0;
            TabControl.AllowDrop = true;
        }

        private void Document_Drop(object sender, DragEventArgs evt) {
            if (evt.Data.GetDataPresent(DataFormats.FileDrop)) {
                var files = (string[])evt.Data.GetData(DataFormats.FileDrop);
                foreach (var file in files) {
                    if (Path.GetExtension(file) == ".pdf") {
                        SelectedDocs.Add(new(DocType.Custom, Path.GetFileName(file), file));
                    }
                }
            }
        }

        private void Document_PreviwDragOver(object sender, DragEventArgs evt) {
            evt.Handled = TabControl.SelectedIndex == 0;
        }

        private void AvaiableDocumentsList_SelectionChanged(object sender, RoutedEventArgs evt) {
            DocumentAddButton.IsEnabled = AvaiableDocumentsList.SelectedIndex != -1;
        }

        private void SelectedDocumentsList_SelectionChanged(object sender, RoutedEventArgs evt) {
            DocumentRemoveButton.IsEnabled = SelectedDocumentsList.SelectedIndex != -1;
            if (SelectedDocumentsList.SelectedItem is SelectedDoc doc) {
                DocumentBox.Header = doc.Name;
                if (doc.Type == DocType.DeliveryConfirmation) {
                    DocumentNonDeliverersInput.Visibility = Visibility.Visible;
                    DocumentFooterLabel.Visibility = Visibility.Visible;
                    DeliveryConfirmationFooterInput.Visibility = Visibility.Visible;
                    CreditNoteFooterInput.Visibility = Visibility.Hidden;
                    DocumentFooterLabel.Margin = new(10, 40, 0, 10);
                } else if (doc.Type == DocType.CreditNote) {
                    DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
                    DocumentFooterLabel.Visibility = Visibility.Visible;
                    DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
                    CreditNoteFooterInput.Visibility = Visibility.Visible;
                    DocumentFooterLabel.Margin = new(10, 10, 0, 10);
                } else {
                    DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
                    DocumentFooterLabel.Visibility = Visibility.Hidden;
                    DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
                    CreditNoteFooterInput.Visibility = Visibility.Hidden;
                }
            } else {
                DocumentBox.Header = "Dokument";
                DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
                DocumentFooterLabel.Visibility = Visibility.Hidden;
                DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
                CreditNoteFooterInput.Visibility = Visibility.Hidden;
            }
        }

        private void DocumentAddButton_Click(object sender, RoutedEventArgs evt) {
            var idx = AvaiableDocumentsList.SelectedIndex;
            if (AvaiableDocumentsList.SelectedItem is not string s)
                return;
            if (idx == 0) {
                SelectedDocs.Add(new(DocType.MemberDataSheet, s, null));
            } else if (idx == 1) {
                SelectedDocs.Add(new(DocType.DeliveryConfirmation, s, (Season!.Year, DocumentNonDeliverersInput.IsChecked == true)));
            } else if (idx >= 2) {
                var name = s.Split(" – ")[^1];
                var pv = Context.PaymentVariants.Single(v => v.Year == Season!.Year && v.Name == name)!;
                SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
            }
            SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
        }

        private void DocumentRemoveButton_Click(object sender, RoutedEventArgs evt) {
            DeleteCommand.Execute(null);
        }

        private void SelectDocumentButton_Click(object sender, RoutedEventArgs evt) {
            var d = new OpenFileDialog() {
                Title = "Dokument auswählen - Elwig",
                DefaultExt = ".pdf",
                Filter = "PDF-Datei (*.pdf)|*.pdf",
                Multiselect = true,
            };
            if (d.ShowDialog() == true) {
                foreach (var file in d.FileNames) {
                    if (Path.GetExtension(file) == ".pdf") {
                        SelectedDocs.Add(new(DocType.Custom, Path.GetFileName(file), file));
                    }
                }
            }
        }

        private async void RecipientsInput_Changed(object sender, RoutedEventArgs evt) {
            var vis = RecipientsCustomInput.IsChecked == true ? Visibility.Hidden : Visibility.Visible;
            MemberBranchLabel.Visibility = vis;
            MemberBranchInput.Visibility = vis;
            MemberKgLabel.Visibility = vis;
            MemberKgInput.Visibility = vis;
            MemberAreaComInput.Visibility = RecipientsAreaComMembersInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden;
            MemberAreaComLabel.Visibility = RecipientsAreaComMembersInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden;
            MemberCustomInput.Visibility = RecipientsCustomInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden;
            await UpdateRecipients();
        }

        private async void MemberInput_SelectionChanged(object sender, RoutedEventArgs evt) {
            await UpdateRecipients();
        }

        private async Task UpdateRecipients() {
            if (RecipientsCustomInput.IsChecked == true) {
                Recipients = MemberCustomInput.SelectedItems.Cast<Member>().ToList();
            } else {
                // FIXME NOT WORKING ON SECOND OPENING OF WINDOW
                var year = (!await Context.Deliveries.AnyAsync()) ? 0 : await Context.Deliveries.Select(d => d.Year).MaxAsync();

                IQueryable<Member> query = Context.Members.Where(m => m.IsActive);
                if (MemberBranchInput.SelectedItems.Count != MemberBranchInput.Items.Count) {
                    var zwst = MemberBranchInput.SelectedItems.Cast<Branch>().Select(b => b.ZwstId).ToList();
                    query = query.Where(m => zwst.Contains(m.ZwstId));
                }
                if (MemberKgInput.SelectedItems.Count != MemberKgInput.Items.Count) {
                    var kgs = MemberKgInput.SelectedItems.Cast<AT_Kg>().Select(k => k.KgNr).ToList();
                    query = query.Where(m => kgs.Contains((int)m.DefaultKgNr));
                }

                if (RecipientsAreaComMembersInput.IsChecked == true) {
                    var vtrg = MemberAreaComInput.SelectedItems.Cast<AreaComType>().Select(a => a.VtrgId).ToList();
                    query = query.Where(m => m.AreaCommitments.Any(a => a.YearFrom <= year && (a.YearTo == null || a.YearTo >= year) && vtrg.Contains(a.VtrgId)));
                } else if (year > 0 && RecipientsDeliveryMembersInput.IsChecked == true) {
                    query = query.Where(m => m.Deliveries.Any(d => d.Year == year));
                } else if (year > 0 && RecipientsNonDeliveryMembersInput.IsChecked == true) {
                    query = query.Where(m => !m.Deliveries.Any(d => d.Year == year));
                }
                Recipients = await query.ToListAsync();
            }
            UpdatePostalEmailRecipients();
        }

        private void EmailInput_Changed(object sender, RoutedEventArgs evt) {
            UpdatePostalEmailRecipients();
        }

        private void UpdatePostalEmailRecipients() {
            EmailAllCount = Recipients.Count(m => m.EmailAddresses.Count > 0);
            EmailWishCount = Recipients.Count(m => m.EmailAddresses.Count > 0 && m.ContactViaEmail);
            PostalAllCount = Recipients.Count();
            PostalWishCount = Recipients.Count(m => m.ContactViaPost);
            var m = EmailAllInput.IsChecked == true ? 3 : EmailWishInput.IsChecked == true ? 2 : 1;
            PostalNoEmailCount = PostalAllCount - (m == 3 ? EmailAllCount : m == 2 ? EmailWishCount : 0);
        }

        private async Task UpdateTextParameters() {
            var changed = false;

            var dcText = DeliveryConfirmationFooterInput.Text.Trim();
            if (dcText.Length == 0) dcText = null;
            if (dcText != App.Client.TextDeliveryConfirmation) {
                App.Client.TextDeliveryConfirmation = dcText;
                changed = true;
            }

            var cdText = CreditNoteFooterInput.Text.Trim();
            if (cdText.Length == 0) cdText = null;
            if (cdText != App.Client.TextCreditNote) {
                App.Client.TextCreditNote = cdText;
                changed = true;
            }

            var emailSubject = EmailSubjectInput.Text.Trim();
            if (emailSubject.Length == 0) emailSubject = null;
            if (emailSubject != App.Client.TextEmailSubject) {
                App.Client.TextEmailSubject = emailSubject;
                changed = true;
            }

            var emailBody = EmailBodyInput.Text.Trim();
            if (emailBody.Length == 0) emailBody = null;
            if (emailBody != App.Client.TextEmailBody) {
                App.Client.TextEmailBody = emailBody;
                changed = true;
            }

            if (changed)
                await App.Client.UpdateValues();
        }

        private void DisposeDocs() {
            PrintDocument?.Dispose();
            PrintDocument = null;
            if (EmailDocuments != null) {
                foreach (var (m, docs) in EmailDocuments) {
                    foreach (var d in docs) {
                        d.Dispose();
                    }
                }
                EmailDocuments = null;
            }
        }

        private void Window_Closed(object sender, EventArgs evt) {
            DisposeDocs();
        }

        private async void GenerateButton_Click(object sender, RoutedEventArgs evt) {
            PreviewButton.IsEnabled = false;
            PrintButton.IsEnabled = false;
            EmailButton.IsEnabled = false;
            Mouse.OverrideCursor = Cursors.AppStarting;
            GenerateButton.IsEnabled = false;

            DisposeDocs();
            await UpdateTextParameters();

            IEnumerable<Member> recipients = Recipients;
            if (OrderMgNrInput.IsChecked == true) {
                recipients = recipients
                    .OrderBy(m => m.MgNr)
                    .ToList();
            } else if (OrderNameInput.IsChecked == true) {
                recipients = recipients
                    .OrderBy(m => m.FamilyName)
                    .ThenBy(m => m.GivenName)
                    .ThenBy(m => m.MgNr)
                    .ToList();
            } else if (OrderPlzInput.IsChecked == true) {
                recipients = recipients
                    .OrderBy(m => m.PostalDest.AtPlz.Plz)
                    .ThenBy(m => m.PostalDest.AtPlz.Ort.Name)
                    .ThenBy(m => m.FamilyName)
                    .ThenBy(m => m.GivenName)
                    .ThenBy(m => m.MgNr)
                    .ToList();
            }

            var doublePaged = DoublePagedInput.IsChecked == true;
            var docs = SelectedDocs.OrderByDescending(d => d.Type).ToList();

            Dictionary<int, IDictionary<int, DeliveryConfirmationDeliveryData>> dcData = [];
            Dictionary<(int, int), (IDictionary<int, CreditNoteDeliveryData>, IDictionary<int, PaymentMember>, BillingData)> cnData = [];
            foreach (var doc in docs) {
                if (doc.Type == DocType.DeliveryConfirmation) {
                    var details = ((int, bool))doc.Details!;
                    var year = details.Item1;
                    dcData[year] = await DeliveryConfirmationDeliveryData.ForSeason(Context.DeliveryParts, year);
                } else if (doc.Type == DocType.CreditNote) {
                    var details = ((int, int))doc.Details!;
                    var year = details.Item1;
                    var avnr = details.Item2;
                    try {
                        cnData[(year, avnr)] = (
                            await CreditNoteDeliveryData.ForPaymentVariant(Context.CreditNoteDeliveryRows, Context.Seasons, year, avnr),
                            await Context.MemberPayments.Where(p => p.Year == year && p.AvNr == avnr).ToDictionaryAsync(c => c.MgNr),
                            BillingData.FromJson((await Context.PaymentVariants.FindAsync(year, avnr))!.Data)
                        );
                    } catch (Exception exc) {
                        MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                        GenerateButton.IsEnabled = true;
                        Mouse.OverrideCursor = null;
                        return;
                    }
                    await Context.GetMemberAreaCommitmentBuckets(year, 0);
                }
            }

            var memberDocs = recipients.Select(m => new {
                Member = m,
                Docs = docs.SelectMany<SelectedDoc, GeneratedDoc>(doc => {
                    if (doc.Type == DocType.Custom) {
                        return [new GeneratedDoc((string)doc.Details!)];
                    } else if (doc.Type == DocType.MemberDataSheet) {
                        return [new GeneratedDoc(new MemberDataSheet(m, Context))];
                    } else if (doc.Type == DocType.DeliveryConfirmation) {
                        var details = ((int, bool))doc.Details!;
                        var year = details.Item1;
                        var include = details.Item2;
                        DeliveryConfirmationDeliveryData data;
                        if (dcData[year].TryGetValue(m.MgNr, out var d)) {
                            data = d;
                        } else if (include) {
                            data = DeliveryConfirmationDeliveryData.CreateEmpty(year, m);
                        } else {
                            return [];
                        }
                        return [new GeneratedDoc(new DeliveryConfirmation(Context, year, m, data))];
                    } else if (doc.Type == DocType.CreditNote) {
                        var details = ((int, int))doc.Details!;
                        var year = details.Item1;
                        var avnr = details.Item2;
                        var data = cnData[(year, avnr)];
                        try {
                            return [new GeneratedDoc(new CreditNote(
                                Context, data.Item2[m.MgNr], data.Item1[m.MgNr],
                                data.Item3.ConsiderContractPenalties,
                                data.Item3.ConsiderTotalPenalty,
                                data.Item3.ConsiderAutoBusinessShares,
                                Context.GetMemberUnderDelivery(year, m.MgNr).GetAwaiter().GetResult()
                            ))];
                        } catch (Exception) {
                            return [];
                        }
                    } else {
                        throw new NotImplementedException("Invalid DocType");
                    }
                }).ToList()
            }).ToList();

            var printMode = PostalAllInput.IsChecked == true ? 3 :
                PostalWishInput.IsChecked == true ? 2 :
                PostalNoEmailInput.IsChecked == true ? 1 : 0;
            var emailMode = EmailAllInput.IsChecked == true ? 2 : EmailWishInput.IsChecked == true ? 1 : 0;

            double printNum = printMode == 3 ? PostalAllCount : printMode == 2 ? PostalWishCount : printMode == 2 ? PostalNoEmailCount : 0;
            double emailNum = emailMode == 2 ? EmailAllCount : emailMode == 1 ? EmailWishCount : 0;
            double totalNum = printNum + emailNum;

            var email = memberDocs
                .Where(d => d.Docs.Count > 0 && d.Member.EmailAddresses.Any() && (emailMode == 2 || (emailMode == 1 && d.Member.ContactViaEmail)))
                .ToDictionary(d => d.Member, m => {
                    var docs = m.Docs.Select(d => d.Doc).ToList();
                    foreach (var doc in docs) {
                        doc!.DoubleSided = false;
                        if (doc is BusinessDocument b)
                            b.IncludeSender = false;
                    };
                    return docs;
                });
            var emailRecipients = email.Select(d => d.Key.MgNr).ToHashSet();
            foreach (var item1 in email.Select((e, i) => new { Index = i, e.Key, e.Value })) {
                foreach (var item2 in item1.Value.Select((d, i) => new { Index = i, Doc = d})) {
                    await item2.Doc.Generate(new Progress<double>(v => {
                        ProgressBar.Value = v * (item2.Index + 1) / item1.Value.Count / totalNum + 100.0 * item1.Index / totalNum;
                    }));
                }
            }
            if (email.Count > 0) {
                EmailDocuments = email;
            }

            var printDocs = memberDocs
                .Where(d =>
                    printMode == 3 ||
                    (printMode == 2 && d.Member.ContactViaPost) ||
                    (printMode == 1 && !emailRecipients.Contains(d.Member.MgNr)))
                .SelectMany(m => {
                    var docs = m.Docs.Select(d => d.Doc).ToList();
                    if (docs.Count == 0 || m.Docs[0].Type == DocType.Custom) {
                        docs.Insert(0, new Letterhead(m.Member));
                    }
                    docs.ForEach(doc => doc.DoubleSided = doublePaged);
                    if (docs.Count > 0 && docs[0] is BusinessDocument b)
                        b.IncludeSender = true;
                    return docs;
                })
                .ToList();

            if (printDocs.Count > 0) {
                var print = Document.Merge(printDocs);
                print.DoubleSided = doublePaged;
                await print.Generate(new Progress<double>(v => {
                    ProgressBar.Value = 100.0 * emailNum / totalNum + v * printNum / totalNum;
                }));
                PrintDocument = print;
            }
            ProgressBar.Value = 100.0;

            GenerateButton.IsEnabled = true;
            Mouse.OverrideCursor = null;
            PreviewButton.IsEnabled = true;
            //PrintButton.IsEnabled = true;
            //EmailButton.IsEnabled = true;
        }

        private void PreviewButton_Click(object sender, RoutedEventArgs evt) {
            var d = new OpenFolderDialog() {
                Title = "Ordner auswählen - Elwig",
            };
            if (d.ShowDialog() == true) {
                Mouse.OverrideCursor = Cursors.AppStarting;
                PrintDocument?.SaveTo($"{d.FolderName}/Print.pdf");
                if (EmailDocuments != null) {
                    foreach (var (m, docs) in EmailDocuments) {
                        var folder = $"{d.FolderName}/E-Mail/{m.AdministrativeName}";
                        Directory.CreateDirectory(folder);
                        foreach (var item in docs.Select((d, i) => new { Index = i, Doc = d })) {
                            var doc = item.Doc;
                            var name = Regex.Replace(doc.Title.Replace('/', '-'), @"[^A-Za-z0-9ÄÜÖẞäöüß-]+", "_");
                            doc.SaveTo($"{folder}/{item.Index + 1:00}.{name}.pdf");
                        }

                    }
                }
                Mouse.OverrideCursor = null;
                Process.Start("explorer.exe", d.FolderName);
            }
        }
    }
}