using System.Net;
using System.Net.Mail;

namespace Fast.Web.Controllers
{
    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class EmailSettingsController : ODataController
    {
        private readonly MyDbContext db;
        private readonly AuthorizationHelper authHelper;
        private readonly IWebHostEnvironment env;

        public EmailSettingsController(MyDbContext context, IWebHostEnvironment env)
        {
            db = context;
            authHelper = new AuthorizationHelper(Main.IsAuthenticationEnabled);
            this.env = env;
        }

        [Permission("Email Settings", PermissionType.View)]
        [Route("[action]")]
        public async Task<IActionResult> GetRequiredData()
        {
            var hasModifyPermission = await authHelper.IsAuthorizedAsync(User, "Email Settings", PermissionType.Modify);

            var connectionTypes = new List<IdName>
            {
                new(0, "No"),
                new(1, "TLS, if available"),
                new(2, "TLS"),
                new(3, "SSL")
            };

            var result = new { hasModifyPermission, connectionTypes };
            return Ok(result);
        }

        [Permission("Email Settings", PermissionType.View)]
        [Route("[action]")]
        public async Task<IActionResult> GetDetail()
        {
            var detail = await (
                from q in db.EmailSettings
                select new EmailSettingsDetail
                {
                    EmailSettingsId = q.Id,
                    SmtpServer = q.SmtpServer,
                    Port = q.Port,
                    UserName = q.UserName,
                    Password = q.Password,
                    ConnectionType = q.ConnectionType
                }
            ).AsNoTracking().FirstAsync();

            return Ok(detail);
        }

        [Permission("Email Settings", PermissionType.Modify)]
        [Route("[action]")]
        public async Task<IActionResult> SaveDetail(EmailSettingsDetail detail)
        {
            int resultId = 0;

            await db.Database.CreateExecutionStrategy().Execute(async () =>
            {
                using var dbContextTransaction = await db.Database.BeginTransactionAsync();
                EmailSetting? dbItem = null;
                dbItem = await (
                    from q in db.EmailSettings
                    select q
                ).FirstOrDefaultAsync();

                if (dbItem == null) //if the item does not exist then add it
                {
                    dbItem = new EmailSetting();
                    db.EmailSettings.Add(dbItem);
                }

                var d = detail;
                dbItem.SmtpServer = d.SmtpServer;
                dbItem.Port = d.Port;
                dbItem.UserName = d.UserName;
                dbItem.Password = d.Password;
                dbItem.ConnectionType = d.ConnectionType;

                await db.SaveChangesAsync();
                resultId = dbItem.Id;

                await dbContextTransaction.CommitAsync();
            });

            return Ok(resultId);
        }

        [Permission("Email Settings", PermissionType.Modify)]
        [AcceptVerbs("POST", "PUT")]
        [Route("SendTestEmail/{address}")]
        public async Task<IActionResult> SendTestEmail(string address, EmailSettingsDetail settings)
        {
            //System.Threading.Thread.Sleep(5000);
            var client = new SmtpClient
            {
                Timeout = 10000,
                Host = settings.SmtpServer,
                Port = settings.Port,
                EnableSsl = settings.ConnectionType == 3,
                UseDefaultCredentials = false,
            };

            if (!client.UseDefaultCredentials)
                client.Credentials = new NetworkCredential(settings.UserName, settings.Password);

            var fromAddress = await (
                from q in db.Notifications
                where q.FromAddress != null
                select q.FromAddress
                ).FirstAsync();

            var mailMessage = new MailMessage
            {
                From = new MailAddress(fromAddress, FastValues.AppName + " Email Test"),
                Subject = "This is a Test",
                Body = "This is a Test"
            };
            mailMessage.To.Add(address);

            if (env.IsDevelopment())
            {
                client.Host = "smtp.gmail.com";
                client.Port = 587;
                client.Credentials = new NetworkCredential("joshlupo@gmail.com", "ixunejvqvkbyqwoe"); //this is a google account "app" password
                client.EnableSsl = true;
            }

            client.Send(mailMessage);

            return Ok();
        }
    }
}
