using MbeSoap;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK5.Core;
using WK5.Core.Basis;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Email;
using WK5.Core.Models;
using WK5.Core.PageModels.Stammdaten.Kunden;
using WK5.Core.PageModels.Verkauf.Aufträge;

namespace WK5_Blazor.Pages.Verkauf.Aufträge
{
    public partial class AuftragStornieren : IDisposable
    {
        [Parameter] public int Auftragsnummer { get; set; }
#nullable disable
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }
#nullable enable
        public AuftragStornierenInput? Input { get; set; }
        public Bestellung? Bestellung { get; set; }

        public bool IstBuchhaltungNotwendig { get; set; }
        public bool IstLieferantNotwendig { get; set; }
        public bool ErfordertZahlartKontodaten { get; set; }
        private Auftrag? _auftrag;
        private TemplateTextCollection Texte { get; set; } = new TemplateTextCollection();

        private EditForm? _editForm;
        protected override async Task OnParametersSetAsync()
        {

            using FbController2 fbController = new FbController2();
            Texte = await TemplateText.GetTemplateTexteAsync(GlobalConfig.IDENTIFIER_AUFTRAG_STORNIEREN, fbController);
            _auftrag = await Auftrag.GetAuftragAsync(Auftragsnummer, fbController);
            Console.WriteLine(Mitarbeiter.PersonalNummer);
            if (_auftrag is null)
            {
                await AddAlertAsync(new AlertBox
                {
                    Message = $"AU-{Auftragsnummer} konnte nicht gefunden werden.",
                    AlertType = AlertType.Danger
                });

                navigationManager.NavigateTo("/Auftraege");
                return;
            }

            if (_auftrag.BELE_L_STORNO)
            {
                await AddAlertAsync(new AlertBox
                {
                    Message = $"AU-{Auftragsnummer} ist bereits storniert.",
                    AlertType = AlertType.Danger
                });
                navigationManager.NavigateTo("/Auftraege");
                return;
            }

            Input = new AuftragStornierenInput(Auftragsnummer, _auftrag.ZahlungsbedingungId)
            {
                Kontoinhaber = _auftrag.Name1
            };

            Input.ValueForTextChanged += Input_ValueForTextChanged;

            IstBuchhaltungNotwendig = Program.AppDaten.Zahlungsbedingungen.IstVorkasse(_auftrag.ZahlungsbedingungId) && _auftrag.BELE_L_BEZAHLT;
            Bestellung = await _auftrag.GetBestellungenAsync(fbController).FirstOrDefaultAsync();
            ErfordertZahlartKontodaten = Program.AppDaten.Zahlungsbedingungen.BenötigtKontodaten(_auftrag.ZahlungsbedingungId);
            IstLieferantNotwendig = Bestellung is not null && !Bestellung.BEST_L_ERLEDIGT;

        }

        private async Task SaveAsync()
        {


            if (_editForm is null || _editForm.EditContext is null || Input is null || _auftrag is null)
            {
                return;
            }

            if (_editForm.EditContext.Validate())
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                EmailController emailController = new EmailController();
                emailController.Html = false;
                await fbController.StartTransactionAsync();
                try
                {
                    await belegService.AuftragStornierenAsync(_auftrag, Input.Begründung, Mitarbeiter.PersonalNummer, fbController);
                    
                    Kundenkontakt kundenKontakt = new Kundenkontakt
                    {
                        KUKO_N_ART = (int)KundenkontaktArten.EMail,
                        KUKO_A_PARTNER = _auftrag.Ansprechpartner,
                        KUKO_L_WIEDERV_ERL = true,
                        KUKO_A_NOTIZ = Input.Begründung,
                        KUKO_WK5_B_LANGNOTIZ = Input.Begründung,
                        KUKO_D_DATE = DateTime.Now,
                        KUKO_A_KUNDNR = _auftrag.Kundennummer,
                        KUKO_N_WIEDERV_USER = Mitarbeiter.PersonalNummer
                    };


                    if (Input.MailAnKunden)
                    {
                        await kundenkontaktService.CreateAsync(kundenKontakt, fbController);

                        RecipientType recipientKundenMail = await _auftrag.ToRecipientTypeAsync(fbController);
                        EmailResponse response = await emailController.SendenAsync
                        (
                            empfängerEmail: recipientKundenMail.Email,
                            betreff: Texte.GetText(GlobalConfig.IDENTIFIER_KEY_STORNIERT_KUNDE_BETREFF).Replace("{{ AUFTRAGSNUMMER }}", Auftragsnummer.ToString()),
                            body: Input.TextKundenMail
                        );

                        if (!response.Success)
                        {
                            await AddAlertAsync(new AlertBox
                            {
                                AlertType = AlertType.Danger,
                                Message = response.Message
                            });
                        }

                    }


                    if (Bestellung is not null && !Bestellung.BEST_L_ERLEDIGT)
                    {
                        await bestellService.BestellungStornierenAsync(Bestellung.Bestellnummer, fbController);

                        if (Input.MailAnLieferanten)
                        {

                            Lieferant? lieferant = await Lieferant.GetLieferantAsync(Bestellung.LieferantenId);
                            if (lieferant is null)
                            {
                                await AddAlertAsync(new AlertBox
                                {
                                    AlertType = AlertType.Danger,
                                    Message = $"Es konnte keine Mail an den Lieferanten geschickt werden, da der Lieferant {Bestellung.LieferantenId} nicht gefunden werden konnte"
                                });
                            }
                            else if (String.IsNullOrWhiteSpace(lieferant.LIEF_A_EMAIL))
                            {
                                await AddAlertAsync(new AlertBox
                                {
                                    AlertType = AlertType.Danger,
                                    Message = $"Es konnte keine Mail an den Lieferanten geschickt werden, da im Lieferanten {lieferant.LIEF_A_NAME1} keine E-Mail hinterlegt ist"
                                });
                            }
                            else
                            {

                                LieferantenKontakt lieferantenKontakt = new LieferantenKontakt
                                {
                                    LFKO_N_LFNR = Bestellung.LieferantenId,
                                    LFKO_N_ART = (int)LieferantenKontaktTyp.Email,
                                    LFKO_N_BESTELLNR = Bestellung.Bestellnummer,
                                    LFKO_D_DATE = DateTime.Now,
                                    LFKO_B_LANGNOTIZ = Input.TextLieferantenMail,
                                    LFKO_A_NOTIZ = Input.TextLieferantenMail
                                };

                                await lieferantenkontaktService.CreateAsync(lieferantenKontakt, fbController);

                                EmailResponse response = await emailController.SendenAsync
                                (
                                    empfängerEmail: lieferant.LIEF_A_EMAIL,
                                    betreff: Texte.GetText(GlobalConfig.IDENTIFIER_KEY_STORNIERT_KUNDE_BETREFF).Replace("{{ AUFTRAGSNUMMER }}", Auftragsnummer.ToString()),
                                    body: Input.TextLieferantenMail
                                );

                                if (!response.Success)
                                {
                                    await AddAlertAsync(new AlertBox
                                    {
                                        AlertType = AlertType.Danger,
                                        Message = response.Message
                                    });
                                }
                            }
                        }
                    }

                    if (Input.MailAnBuchhaltung)
                    {
                        string empfängerBuchhaltung = ErfordertZahlartKontodaten
                            ? await GlobalConfig.GetConfigAsync(GlobalConfig.AUFTRAG_STORNIEREN_BUCHHALTUNG_MAIL_CONFIG_NAME, fbController)
                            : await GlobalConfig.GetConfigAsync(GlobalConfig.AUFTRAG_STORNIEREN_DIRECT_PAYMENT_URL_CONFIG_NAME, fbController);

                        EmailResponse response = await emailController.SendenAsync
                        (
                            empfängerEmail: empfängerBuchhaltung,
                            betreff: Texte.GetText(GlobalConfig.IDENTIFIER_KEY_STORNIERT_BUCHHALTUNG_BETREFF).Replace("{{ AUFTRAGSNUMMER }}", Auftragsnummer.ToString()),
                            body: Input.TextBuchhaltungsMail
                        );

                        if (!response.Success)
                        {
                            await AddAlertAsync(new AlertBox
                            {
                                AlertType = AlertType.Danger,
                                Message = response.Message
                            });
                        }

                    }


                    await AddAlertAsync(new AlertBox
                    {
                        AlertType = AlertType.Success,
                        Message = $"AU-{Auftragsnummer} wurde erfolgreich storniert"
                    });

                    await fbController.CommitChangesAsync();

                    navigationManager.NavigateTo("/Auftraege");
                }
                catch (Exception)
                {
                    await fbController.RollbackChangesAsync();
                    throw;
                }


            }
        }

        #region Generierung der Texte
        private void Input_ValueForTextChanged(object? sender, EventArgs e)
        {
            GeneriereKundenMailText();
            GeneriereLieferantenMailText();
            GeneriereBuchhaltungMailText();
            StateHasChanged();
        }

        private void GeneriereKundenMailText()
        {
            if (Input is null || _auftrag is null)
            {
                return;
            }

            StornierTemplate? template = Program.AppDaten.StornierTemplates[Input.Begründung];
            TemplateText? textTemplate = null;
            if (template is not null)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(template.STTE_B_TEXT);
                if (IstBuchhaltungNotwendig && ErfordertZahlartKontodaten)
                {
                    if (Input.BankdatenErhalten)
                    {
                        textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_KUNDE_VORKASSE_BANKDATEN] ?? new TemplateText();
                        sb.AppendLine(textTemplate.TEXT_B_TEXT);
                    }
                    else
                    {
                        textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_KUNDE_VORKASSE_KEINE_BANKDATEN] ?? new TemplateText();
                        sb.AppendLine(textTemplate.TEXT_B_TEXT);
                    }
                }
                else if (IstBuchhaltungNotwendig && !ErfordertZahlartKontodaten)
                {
                    textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_KUNDE_VORKASSE_DIRECT_PAYMENT] ?? new TemplateText();
                    sb.AppendLine(textTemplate.TEXT_B_TEXT);
                }

                sb.AppendLine(GlobalConfig.Configuration.FirmenDaten.Impressum());
                string anrede = String.IsNullOrWhiteSpace(_auftrag.Ansprechpartner) ? "Sehr geehrte Damen und Herren" : _auftrag.Anrede;

                if (!anrede.Equals("Sehr geehrte Damen und Herren", StringComparison.OrdinalIgnoreCase) && !String.IsNullOrWhiteSpace(_auftrag.Ansprechpartner))
                {
                    anrede = $"{anrede} {_auftrag.Ansprechpartner},";
                }
                else
                {
                    anrede = $"{anrede},";
                }

                Input.TextKundenMail = sb.ToString()
                    .Replace("{{ ANREDE }}", anrede)
                    .Replace("{{ AUFTRAGSNUMMER }}", Auftragsnummer.ToString())
                    .Replace("{{ IBAN }}", Input.Iban)
                    .Replace("{{ BIC }}", Input.Bic)
                    .Replace("{{ KONTOINHABER }}", Input.Kontoinhaber)
                    .Replace("{{ ZAHLUNGSBEDINUNG }}", Program.AppDaten.GetZahlungsbedingungText(_auftrag.ZahlungsbedingungId))
                    .Replace("{{ STORNIER_GRUND}}", Input.Begründung)
                    ;
            }
        }

        private void GeneriereLieferantenMailText()
        {
            if (Input is null || Bestellung is null)
            {
                return;
            }

            TemplateText? textTemplate = null;

            StringBuilder sb = new StringBuilder();
            if (!String.IsNullOrWhiteSpace(Bestellung.BEST_A_BESTAET_NR_LIEF))
            {
                textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_LIEFERANT_MIT_AUFTRAGSBESTAEGIGUNG] ?? new TemplateText();
            }
            else
            {
                textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_LIEFERANT] ?? new TemplateText();//, $"Der Key {GlobalConfig.IDENTIFIER_KEY_STORNIERT_LIEFERANT} konnte nicht in der Datenbank gefunden werden" ?? ArgumentNullException(nameof(textTemplate));
            }



            sb.AppendLine(textTemplate.TEXT_B_TEXT);
            sb.AppendLine(GlobalConfig.Configuration.FirmenDaten.Impressum());

            Input.TextLieferantenMail = sb.ToString()
                .Replace("{{ ANREDE }}", "Sehr geehrte Damen und Herren,")
                .Replace("{{ AUFTRAGSNUMMER }}", Auftragsnummer.ToString())
                .Replace("{{ BESTELLNUMMER }}", Bestellung.Bestellnummer.ToString())
                .Replace("{{ AUFTRAGSBESTÄTIGUNGS_NUMMER }}", Bestellung.BEST_A_BESTAET_NR_LIEF ?? String.Empty)
                .Replace("{{ STORNIER_GRUND}}", Input.Begründung)
                ;
        }

        private void GeneriereBuchhaltungMailText()
        {
            if (Input is null || _auftrag is null)
            {
                return;
            }

            TemplateText? textTemplate = null;

            StringBuilder sb = new StringBuilder();


            if (ErfordertZahlartKontodaten && Input.BankdatenErhalten)
            {
                textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_BUCHHALTUNG_BANKDATEN] ?? new TemplateText();
            }
            else if (!ErfordertZahlartKontodaten)
            {
                textTemplate = Texte[GlobalConfig.IDENTIFIER_KEY_STORNIERT_BUCHHALTUNG] ?? new TemplateText();
            }
            else
            {
                return;
            }


            sb.AppendLine(textTemplate.TEXT_B_TEXT);


            Input.TextBuchhaltungsMail = sb.ToString()
                .Replace("{{ AUFTRAGSNUMMER }}", Auftragsnummer.ToString())
                .Replace("{{ KUNDENNAME }}", _auftrag.Name1)
                .Replace("{{ KUNDENNUMMER }}", _auftrag.Kundennummer)
                .Replace("{{ STORNIER_GRUND }}", Input.Begründung)
                .Replace("{{ IBAN }}", Input.Iban)
                .Replace("{{ BIC }}", Input.Bic)
                .Replace("{{ KONTOINHABER }}", Input.Kontoinhaber)
                .Replace("{{ ZAHLUNGSBEDINGUNG }}", Program.AppDaten.GetZahlungsbedingungText(Input.ZahlungsbedingungId))
                .Replace("{{ STORNIER_GRUND}}", Input.Begründung)
                ;
        }

        #endregion
        #region IDisposable
        public void Dispose()
        {
            if (Input is not null)
            {
                Input.ValueForTextChanged -= Input_ValueForTextChanged;
            }
        }
        #endregion
    }
}
