using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Net.NetworkInformation;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace WK5.Core.Email.Provider
{
    /// <summary>
    /// Der Email Versand für SMTP Daten
    /// </summary>
    public class SmtpProvider : IMailProvider
    {
        /// <summary>
        /// Die Anmeldedaten für den SMTP Server
        /// </summary>
        public MailCredentials Credentials { get; set; }
        /// <summary>
        /// Erstellt eine neue Instanz des <see cref="SmtpProvider"/> mit den angegebenen Credentials
        /// </summary>
        /// <param name="credentials">Die Credentials die zur Anmeldung genutzt werden sollen</param>
        public SmtpProvider(MailCredentials credentials)
        {
            Credentials = credentials;
        }

        /// <summary>
        /// Sendet eine Email über die SMTP Schnittstelle raus
        /// </summary>
        /// <param name="absender">Der Absender der Email</param>
        /// <param name="empfänger">Eine Liste von Email Adressen an die die Nachricht gehen soll</param>
        /// <param name="betreff">Der Betreff der Email</param>
        /// <param name="body">Der Inhalt der Email</param>
        /// <param name="html">Gibt an ob die Email im HTML Format ist oder nicht</param>
        /// <param name="anhänge">Eine Liste von Anhängen die mitgesendet werden sollen</param>
        /// <param name="bcc">Eine Liste von Email Adresse die im Blind Carbon Copy drinstehen sollen</param>
        /// <param name="cc">Eine Liste von Email Adresse die im Carbon Copy drinstehen sollen</param>
        /// <returns></returns>
        public EmailResponse Senden(EmailAbsender absender, List<string> empfänger, string betreff, string body, bool html = true, List<EmailAnhang>? anhänge = null, List<string>? bcc = null, List<string>? cc = null)
        {
            using MailMessage msg = new MailMessage();
            msg.IsBodyHtml = html;
            foreach (string email in empfänger)
            {
                msg.To.Add(email);
            }

            if (bcc is not null)
            {
                foreach (string bccMail in bcc)
                {
                    msg.Bcc.Add(bccMail);
                }
            }

            if (cc is not null)
            {
                foreach (string ccMail in cc)
                {
                    msg.CC.Add(ccMail);
                }
            }

            msg.Subject = betreff;
            msg.Body = body;
            msg.BodyEncoding = Encoding.UTF8;
            msg.From = new MailAddress(absender.Email, absender.Name); ;
            msg.ReplyToList.Add(new MailAddress(absender.ReplyTo, absender.Name));

            if (anhänge is not null)
            {
                foreach (EmailAnhang anhang in anhänge)
                {
                    try
                    {
                        StreamReader reader = new StreamReader(anhang.Pfad!);
                        Attachment attach = new Attachment(reader.BaseStream, anhang.Name);
                        msg.Attachments.Add(attach);
                    }
                    catch (Exception ex)
                    {
                        return new EmailResponse(false, $"#EMAIL3 - SMTP({Credentials.Host}): {ex}");
                    }
                }
            }

            using SmtpClient smtp = new SmtpClient(Credentials.Host, Credentials.Port);
            NetworkCredential credential = new NetworkCredential(Credentials.User, Credentials.Password);
            smtp.UseDefaultCredentials = false;
            smtp.Credentials = credential;
            smtp.EnableSsl = Credentials.SSL;

            try
            {
                smtp.Send(msg);
            }
            catch (Exception ex)
            {
                string message = $"#EMAIL2 - SMTP({Credentials.Host}) Fehler: {ex}";
                if (ex.InnerException != null && !String.IsNullOrWhiteSpace(ex.InnerException.Message))
                {
                    message += $" | {ex.InnerException.Message}";
                }
                return new EmailResponse(false, message);
            }

            return new EmailResponse(true, "");
        }
    }
}
