using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Quartz;
using SolarPower.Models;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace SolarPower.Quartz.Jobs
{
    [DisallowConcurrentExecution]
    public class SendEmailJob : IJob
    {
        private readonly ILogger<SendEmailJob> logger;
        private readonly IOptions<SMTPConfig> _options;
        private readonly INoticeScheduleRepository noticeScheduleRepository;


        private SMTPConfig smtp;

        public SendEmailJob(
            ILogger<SendEmailJob> logger,
            IOptions<SMTPConfig> options,
            INoticeScheduleRepository noticeScheduleRepository)
        {
            this.logger = logger;
            this.smtp = options.Value;
            this.noticeScheduleRepository = noticeScheduleRepository;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                //取得要寄信的列表
                logger.LogInformation("【SendEmailJob】【任務開始】");
                var noticeSchedules = await noticeScheduleRepository.GetNotYetDelivery();

                var updateNoticeSchedules = new List<NoticeSchedule>();
                foreach (var notice in noticeSchedules)
                {
                    if (notice.RecipientEmail != null && IsValidEmail(notice.RecipientEmail)) {
                        var attachments = new List<string>();
                        var recipientEmails = new List<string>()
                        {
                            notice.RecipientEmail
                        };
                        if (!string.IsNullOrEmpty(notice.Attachment))
                        {
                            attachments = notice.Attachment.Split(',').ToList();
                        }
                        var result = Send(recipientEmails, notice.Subject, notice.Content, attachments);

                        if (result.CompareTo("成功") == 0)
                        {
                            NoticeSchedule noticeSchedule = new NoticeSchedule();
                            noticeSchedule.Id = notice.Id;
                            noticeSchedule.IsDelivery = 1;
                            noticeSchedule.DeliveryAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                            updateNoticeSchedules.Add(noticeSchedule);
                        }
                        else
                        {
                            NoticeSchedule noticeSchedule = new NoticeSchedule();
                            noticeSchedule.Id = notice.Id;
                            noticeSchedule.IsDelivery = 2;
                            noticeSchedule.DeliveryAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                            noticeSchedule.Reason = result;

                            updateNoticeSchedules.Add(noticeSchedule);
                        }

                        List<string> properties = new List<string>()
                        {
                            "Id",
                            "IsDelivery",
                            "DeliveryAt"
                        };

                        await noticeScheduleRepository.UpdateList(updateNoticeSchedules, properties);
                    }
                }
                logger.LogInformation("【SendEmailJob】【任務完成】");

            }
            catch (Exception exception)
            {
                logger.LogError("【{0}】{1}", "SendEmailJob", exception.Message);
            }
        }

        private string Send(List<string> recipientEmails, string subject, string content, List<string> attachments)
        {
            var reason = string.Empty;
            var CanDoSend = true;
            MailMessage MyMail = new MailMessage();

            MyMail.SubjectEncoding = System.Text.Encoding.UTF8;//郵件標題編碼
            MyMail.BodyEncoding = System.Text.Encoding.UTF8; //郵件內容編碼
            MyMail.IsBodyHtml = true; //是否使用html格式
            var kkk = $"太陽能電站管理系統通知 <{smtp.UserName}>";
            MyMail.From = new System.Net.Mail.MailAddress(kkk); //寄件人
            foreach (var email in recipientEmails)
            {
                MyMail.To.Add(email); //設定收件者Email
            }

            MyMail.Subject = subject; //主題
            MyMail.Body = content; //設定信件內容

            foreach (var attachment in attachments)
            {
                var directoryBase = Directory.GetCurrentDirectory();
                var filePath = @$"{directoryBase}\wwwroot{attachment}";

                if (File.Exists(filePath))
                {
                    var data = new Attachment(filePath);
                    MyMail.Attachments.Add(data);
                }
                else
                {
                    CanDoSend = false;
                    reason = "失敗 - 檔案遺失";
                    break;
                }
            }

            //讀取 SMTP Config
            if (CanDoSend)
            {
                SmtpClient MySMTP = new SmtpClient(smtp.Host, smtp.Port);
                MySMTP.EnableSsl = smtp.EnableSsl;
                MySMTP.Credentials = new System.Net.NetworkCredential(smtp.UserName, smtp.Password);
                try
                {
                    MySMTP.Send(MyMail);
                    MySMTP.Dispose();
                    MyMail.Dispose(); //釋放資源

                    return "成功";
                }
                catch (Exception ex)
                {
                    string json = System.Text.Json.JsonSerializer.Serialize(recipientEmails);
                    logger.LogError("【SendEmailJob】 " + "寄送信件失敗");
                    logger.LogError("【SendEmailJob】 - Emails:" + json);
                    logger.LogError("【SendEmailJob】 - Exception:" + ex.Message);

                    return "失敗 - " + ex.Message;
                }
            }
            else
            {
                return reason;
            }
            
        }

        bool IsValidEmail(string strIn)
        {
            // Return true if strIn is in valid e-mail format.
            return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }

    }
}
