//Wenn diese Option eingeschaltet ist, gehen alle Emails an software@karley.eu
#if DEBUG
#define EMAIL_DEBUG
#endif

// Schaltet ein das Tobit David als Email Versandart genutzt wird
#define USE_DAVID
// Schaltet ein das der interne SMTP (Tobit) als Email Versandart genutzt wird
#define USE_SMTP_INTERN
// Schaltet ein das der externe SMTP (Strato) als Email Versandart genutzt wird
#define USE_SMTP_EXTERN

using KarleyLibrary.Erweiterungen;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WK5.Core.Email.Provider;
using WK5.Core.Models;

namespace WK5.Core.Email
{
    /// <summary>
    /// EmailController über den zentral alle Emails mit Anhängen etc. Abgehandelt werden können. Wählt hierbei automatisch zwischen Tobit David, internem SMTP und externem SMTP 
    /// in dieser Reihenfolge mit Error Rollover
    /// </summary>
    public class EmailController
    {
        /// <summary>
        /// Die Standard Absende Adresse wenn keine andere spezifiziert wurde
        /// </summary>
        public static EmailAbsender KarleyAbsender { get; set; } = new EmailAbsender(GlobalConfig.Configuration.FirmenDaten.Firmenname, GlobalConfig.Configuration.FirmenDaten.Email, GlobalConfig.Configuration.FirmenDaten.Email);

        /// <summary>
        /// Gibt an ob der Controller Emails als HTML versenden soll
        /// </summary>
        public bool Html { get; set; } = true;

        /// <summary>
        /// Erstellt und versendet eine Email mit den angegebenen Parametern
        /// </summary>
        /// <param name="empfänger">Eine Liste aller Email Adressen die diese Nachricht empfangen sollen</param>
        /// <param name="betreff">Der Betreff der Nachricht</param>
        /// <param name="body">Der Inhalt der Nachricht</param>
        /// <param name="anhänge">Eine Liste mit allen zu übermittelnden Anhängen</param>
        /// <param name="absender">Der Absendern sofern nicht der Standard Karley Absender</param>
        /// <param name="cc">Eine Liste mit Empfängern die im Carbon Copy mitgesendet werden sollen</param>
        /// <param name="bcc">Eine Liste mit Empfängern die im Blind Carbon Copy mitgesendet werden sollen</param>
        /// <returns>Gibt eine Email Response zurück die indiziert ob der Versand erfolgreich war oder nicht</returns>
        private async Task<EmailResponse> SendenAsync(List<string> empfänger, string betreff, string body, List<EmailAnhang>? anhänge = null, EmailAbsender? absender = null, List<string>? cc = null, List<string>? bcc = null)
        {
            anhänge ??= new List<EmailAnhang>();
            cc ??= new List<string>();
            bcc ??= new List<string>();
            absender ??= KarleyAbsender;

            List<string> recipients = new List<string>();

            if (empfänger.Count <= 0)
            {
                return new EmailResponse(false, "#EMAIL1 - Es muss eine Empfänger Addresse angegeben werden.");
            }

            foreach (string emp in empfänger)
            {
                if (!String.IsNullOrWhiteSpace(emp))
                {
                    string recp = emp.Trim();
                    if (StringErweiterung.IstEmail(recp))
                    {
                        recipients.Add(recp);
                    }
                }
            }

            List<string> BCC = new List<string>
            {
                "ausgang@karley.eu"
            };

#if EMAIL_DEBUG
            betreff += $"<DEBUG><Target: {String.Join(',', recipients)}>";
            recipients = new List<string>() { "software@karley.eu" };
#endif

            string providerName = "Unbekannt";
            EmailResponse response = new EmailResponse(false);
            // Wir versuchen die Mail von oben nach unten zu versenden, bis success
#if USE_DAVID
            try
            {
                DavidProvider david = new DavidProvider(GlobalConfig.Configuration.David);
                response = david.Senden(absender ?? KarleyAbsender, recipients, betreff, body, Html, anhänge, BCC, cc);
                providerName = "David";
            }
            catch (Exception ex)
            {
                Log.Logger.Error($"#DAVID_MAIL_VERSAND1 - {ex}");
            }
#endif

#if USE_SMTP_INTERN
            if (!response.Success)
            {
                try
                {
                    SmtpProvider internSmtp = new SmtpProvider(GlobalConfig.Configuration.SMTPIntern);
                    response = internSmtp.Senden(absender ?? KarleyAbsender, recipients, betreff, body, Html, anhänge, BCC, cc);
                    providerName = "SMTP (Intern)";
                }
                catch (Exception ex)
                {
                    Log.Logger.Error($"#DAVID_SMTP_INTERN1 - {ex}");
                }
            }
#endif

#if USE_SMTP_EXTERN
            if (!response.Success)
            {
                try
                {
                    SmtpProvider externSmtp = new SmtpProvider(GlobalConfig.Configuration.SMTPExtern);
                    response = externSmtp.Senden(absender ?? KarleyAbsender, recipients, betreff, body, Html, anhänge, BCC, cc);
                    providerName = "SMTP (Extern)";
                }
                catch (Exception ex)
                {
                    Log.Logger.Error($"#DAVID_SMTP_EXTERN1 - {ex}");
                }
            }
#endif

            await EmailLogs.CreateAsync(String.Join(';', recipients), betreff, body, providerName, response.Success, !response.Success ? response.Message : null);

            if (!response.Success)
            {
                try
                {
                    string dateien = String.Join("<br/><br/>", anhänge.Select(x => $"Dateiname: {x.Name}<br/>Dateipfad: {x.Pfad}"));
                    string FehlerText = $@"<h1>Fehler beim Senden einer Email über die Email Klasse</h1>
                                            </br><br/>
                                            Fehler: {response.Message}<br/>
                                            Email Empfänger: {String.Join(',', empfänger)}<br/>
                                            Email Betreff: {betreff}<br/>
                                            Email Anhänge:<br/>{dateien}<br/>
                                            Email Inhalt:<br/><br/>{body}";

                    FehlerText += $@"Email Inhalt:<br/><br/>{body}";

                    SmtpProvider internSmtp = new SmtpProvider(GlobalConfig.Configuration.SMTPIntern);
                    internSmtp.Senden(KarleyAbsender, new List<string> { "info@karley.eu" }, $"Fehler beim senden einer Email an: {String.Join(',', recipients)}", FehlerText, Html, anhänge.Where(x => x.IsValid()).ToList());
                }
                catch (Exception ex)
                {                  
                }

            }

            return response;
        }

        /// <summary>
        /// Erstellt und versendet eine Email mit den angegebenen Parametern
        /// </summary>
        /// <param name="empfängerEmail">Eine Zeichenkette die den Empfänger spezifizert. Mehrere Empfänger können durch ; getrennt werden</param>
        /// <param name="betreff">Der Betreff der Nachricht</param>
        /// <param name="body">Der Inhalt der Nachricht</param>
        /// <param name="anhänge">Eine Liste mit allen zu übermittelnden Anhängen</param>
        /// <param name="absender">Der Absendern sofern nicht der Standard Karley Absender</param>
        /// <param name="cc">Eine Liste mit Empfängern die im Carbon Copy mitgesendet werden sollen</param>
        /// <param name="bcc">Eine Liste mit Empfängern die im Blind Carbon Copy mitgesendet werden sollen</param>
        /// <returns>Gibt eine Email Response zurück die indiziert ob der Versand erfolgreich war oder nicht</returns>
        public Task<EmailResponse> SendenAsync(string empfängerEmail, string betreff, string body, List<EmailAnhang>? anhänge = null, EmailAbsender? absender = null, List<string>? cc = null, List<string>? bcc = null)
        {
            if (String.IsNullOrWhiteSpace(empfängerEmail))
            {
                return Task.FromResult(new EmailResponse(false, "#EMAIL1 - Es muss eine Empfänger Addresse angegeben werden."));
            }

            List<string> tmpEmpfänger = empfängerEmail.Split(';').ToList();
            List<string> empfänger = new List<string>();

            //Wir trimmen die empfänger, um Fehler beim Email Versand wegen leading oder trailing whitespaces zu verhindern
            for (int i = 0; i < tmpEmpfänger.Count; i++)
            {
                string emp = tmpEmpfänger[i];
                if (!String.IsNullOrWhiteSpace(emp))
                {
                    emp = emp.Trim();
                    if (StringErweiterung.IstEmail(emp))
                    {
                        empfänger.Add(emp);
                    }
                    else
                    {
                        return Task.FromResult(new EmailResponse(false, $"Die Email Adresse {emp} konnte nicht erfolgreich validiert werden!"));
                    }
                }
            }

            return SendenAsync(empfänger, betreff, body, anhänge, absender, cc, bcc);
        }

        /// <summary>
        /// Sendet eine Fehleremail an den spezifizierten Empfänger
        /// </summary>
        /// <param name="betreff">Der Betreff der Fehler Nachricht</param>
        /// <param name="body">Der Inhalt der Fehler Nachricht</param>
        /// <param name="empfänger">Der Empfänger der Fehler Nachricht</param>
        /// <param name="anhänge">Eine Liste mit Anhängen die der Fehlernachricht beigelegt werden soll</param>
        /// <returns>Gibt einen erwartbaren Task zurück</returns>
        public static async Task FehlerMailSendenAsync(string betreff, string body, string empfänger = "software@karley.eu", List<EmailAnhang>? anhänge = null)
        {
            EmailController mailer = new EmailController();
            await mailer.SendenAsync(empfänger, betreff, body, anhänge);
        }
    }
}
