using HrynCo.NotificationService.DAL.Abstract.Providers; using HrynCo.NotificationService.Services.EmailChannels.Create; using HrynCo.NotificationService.Services.EmailChannels.Delete; using HrynCo.NotificationService.Services.EmailChannels.Get; using HrynCo.NotificationService.Services.EmailChannels.GetAll; using HrynCo.NotificationService.Services.EmailChannels.Update; using HrynCo.NotificationService.Web.Controllers.Admin.ViewModels; using MediatR; using Microsoft.AspNetCore.Mvc; using System.Net; using System.Net.Mail; namespace HrynCo.NotificationService.Web.Controllers.Admin; [Route("admin/channels")] public class AdminChannelsController : Controller { private readonly IMediator _mediator; public AdminChannelsController(IMediator mediator) { _mediator = mediator; } // GET /admin/channels [HttpGet("")] public async Task Index(CancellationToken ct) { var result = await _mediator.Send(new GetAllEmailChannelsQuery(), ct); if (!result.IsSuccess) { ModelState.AddModelError("", result.Error?.Message ?? "Failed to load channels."); return View(Array.Empty()); } return View(result.Result); } // GET /admin/channels/create [HttpGet("create")] public IActionResult Create() { return View("Edit", new EmailChannelEditViewModel()); } // GET /admin/channels/{id} [HttpGet("{id:guid}")] public async Task Edit(Guid id, CancellationToken ct) { var result = await _mediator.Send(new GetEmailChannelQuery(id), ct); if (!result.IsSuccess || result.Result is null) return NotFound(); var channel = result.Result; var smtp = channel.Settings as SmtpChannelSettings ?? new SmtpChannelSettings { Host = "", Username = "", Password = "", FromEmail = "", FromName = "" }; var vm = new EmailChannelEditViewModel { Id = channel.Id, ServiceName = channel.ServiceName, Priority = channel.Priority, EmailChannelType = channel.EmailChannelType, DailyLimit = channel.DailyLimit, MonthlyLimit = channel.MonthlyLimit, WarnThresholdPercent = channel.WarnThresholdPercent, IsActive = channel.IsActive, Host = smtp.Host, Port = smtp.Port, Username = smtp.Username, Password = smtp.Password, UseSsl = smtp.UseSsl, FromEmail = smtp.FromEmail, FromName = smtp.FromName }; return View(vm); } // POST /admin/channels/save [HttpPost("save")] [ValidateAntiForgeryToken] public async Task Save(EmailChannelEditViewModel model, CancellationToken ct) { if (!ModelState.IsValid) return View("Edit", model); var smtpSettings = new SmtpChannelSettings { Host = model.Host, Port = model.Port, Username = model.Username, Password = model.Password, UseSsl = model.UseSsl, FromEmail = model.FromEmail, FromName = model.FromName }; if (model.IsNew) { var command = new CreateEmailChannelCommand( model.ServiceName, model.Priority, EmailChannelType.Smtp, smtpSettings, model.DailyLimit, model.MonthlyLimit, model.WarnThresholdPercent, model.IsActive); var result = await _mediator.Send(command, ct); if (!result.IsSuccess) { ModelState.AddModelError("", result.Error?.Message ?? "Failed to create channel."); return View("Edit", model); } } else { var command = new UpdateEmailChannelCommand( model.Id, model.Priority, smtpSettings, model.DailyLimit, model.MonthlyLimit, model.WarnThresholdPercent, model.IsActive); var result = await _mediator.Send(command, ct); if (!result.IsSuccess) { ModelState.AddModelError("", result.Error?.Message ?? "Failed to update channel."); return View("Edit", model); } } return RedirectToAction(nameof(Index)); } // POST /admin/channels/{id}/test [HttpPost("{id:guid}/test")] public async Task Test(Guid id, [FromBody] TestChannelRequest request, CancellationToken ct) { var result = await _mediator.Send(new GetEmailChannelQuery(id), ct); if (!result.IsSuccess || result.Result is null) return NotFound(new { success = false, message = "Channel not found." }); if (result.Result.Settings is not SmtpChannelSettings smtp) return BadRequest(new { success = false, message = "Only SMTP channels are supported." }); try { using var client = new SmtpClient(smtp.Host, smtp.Port) { EnableSsl = smtp.UseSsl, Credentials = string.IsNullOrWhiteSpace(smtp.Username) ? null : new NetworkCredential(smtp.Username, smtp.Password) }; var message = new MailMessage { From = new MailAddress(smtp.FromEmail, smtp.FromName), Subject = "✅ Test email from Notification Service", Body = $"This is a test email sent from the Notification Service admin panel.\n\nChannel: {result.Result.ServiceName}\nHost: {smtp.Host}:{smtp.Port}", IsBodyHtml = false }; message.To.Add(request.ToEmail); await client.SendMailAsync(message, ct); return Ok(new { success = true, message = $"Test email sent to {request.ToEmail}." }); } catch (Exception ex) { return Ok(new { success = false, message = ex.Message }); } } // POST /admin/channels/{id}/delete [HttpPost("{id:guid}/delete")] [ValidateAntiForgeryToken] public async Task Delete(Guid id, CancellationToken ct) { await _mediator.Send(new DeleteEmailChannelCommand(id), ct); return RedirectToAction(nameof(Index)); } } public record TestChannelRequest(string ToEmail);