using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; using LCU.API.Collections.RepoApi.Configuration; using LCU.Shared.Collections.RepoApiLib.Models; using LCU.Shared.Collections.RepoApiLib.Models.AutoIms; using LCU.Shared.Collections.RepoApiLib.Models.Consumer; using LCU.Shared.Common.NotificationApiLib.Models; using Microsoft.EntityFrameworkCore.Internal; using Newtonsoft.Json; using Serilog; namespace LCU.API.Collections.RepoApi.Services { public class Emailer : IEmailer { private readonly IHttpClientFactory _httpClientFactory; private readonly RepoApiConfiguration _configuration; private readonly IEventAlertService _eventAlertService; private const string O4RStatus = "O4R"; public Emailer(IHttpClientFactory httpClientFactory, RepoApiConfiguration configuration, IEventAlertService eventAlertService) { _httpClientFactory = httpClientFactory; _configuration = configuration; _eventAlertService = eventAlertService; } public async Task SendMessageAsync(List recipient, string subject, string body) { var emailRequest = new EmailRequest { Recipient = recipient, Subject = subject, Body = body }; var encoded = JsonConvert.SerializeObject(emailRequest); try { var client = _httpClientFactory.CreateClient(); var c = new StringContent(encoded, Encoding.UTF8, "application/json"); HttpResponseMessage response = await client.PostAsync(_configuration.NotificationsEmailUrl, c); response.EnsureSuccessStatusCode(); return response; } catch (Exception ex) { Log.Error(ex, "An exception was caught trying to send an email via Notifications API."); return null; } } public async Task SendFloorPriceAcceptedEmail(bool isManual, string accountNo, decimal? oldFloorPrice, decimal? newFloorPrice) { var subject = isManual ? "Manual Floor Price Set" : "Automated Floor Price Set"; var body = string.Format(subject + " for account {0} from {1} to {2}.", accountNo, oldFloorPrice?.ToString("C2", CultureInfo.CurrentCulture), newFloorPrice?.ToString("C2", CultureInfo.CurrentCulture)); return await SendMessageAsync(_configuration.FloorPriceAcceptedRecipients, subject, body); } public async Task SendSurplusDeficiencyLetterEmailAsync(RepoAccount repoAccount) { var message = "Please Send the Surplus Deficiency letter. Please notify the Repo Specialists when the letter has been sent, so that this account can be closed in Repo Manager.

"; var member = repoAccount.Borrowers?.First(b => b.OwnershipType == 6); var memberName = "Member Name: " + member?.IndividualName + "
"; var accountNo = "Account No: " + repoAccount.AccountNo + "
"; return await SendMessageAsync(_configuration.CollectionsClerkRecipients, "Refunds Recieved", string.Concat(message, memberName, accountNo)); } public async Task MaybeSendO4rNoCollateralEmail(RepoAccount repoAccount) { if (repoAccount != null && repoAccount.DateClosed == null && repoAccount.Status == O4RStatus) { var subject = "O4R No Collateral"; var body = string.Format("Account {0} set to O4R with no collateral.", repoAccount.AccountNo); return await SendMessageAsync(_configuration.RepoManagerAdminRecipients, subject, body); } return new HttpResponseMessage { StatusCode = HttpStatusCode.OK }; } public async Task SendAlertSummaryEmailWithEndTime(DateTime endTime) { var startTime = endTime.AddHours(-1); var eventAlerts = _eventAlertService.ListWithinDateRange(startTime, endTime).GetAwaiter().GetResult(); var subject = "Repo Manager Alerts " + endTime.ToString("MM-dd-yyyy HH:mm:ss"); var body = "

" + subject + "


"; foreach (var eventAlert in eventAlerts) { var entry = CreateAlertEmailEntry(eventAlert); if (!string.IsNullOrEmpty(entry)) { body += CreateAlertEmailEntry(eventAlert) + "

"; } } if (!eventAlerts.Any()) { body += "No new alerts."; } return await SendMessageAsync(_configuration.CollectionsRecipients, subject, body); } private string CreateAlertEmailEntry(EventAlert eventAlert) { var accountNo = "Account No: " + eventAlert.AccountNo + "
"; var alert = "Alert: " + eventAlert.Message + "
"; var url = eventAlert.RepoId != null ? _configuration.RepoManagerAccountUrl + eventAlert.RepoId : ""; var link = eventAlert.RepoId != null ? string.Format("{0}", url) + "
" : ""; return string.Concat(accountNo, alert, link); } public void SendSummaryEmail(IReadOnlyCollection imported, IReadOnlyCollection floors) { Log.Debug("Sending AutoIMS Import Email"); var subject = "Landmark Auto IMS Import " + DateTime.Now; var reports = new List(); if (imported == null || floors == null) { Log.Error("Null result sets passed to SendSummaryEmail"); return; } foreach (var importResultRow in imported) { reports.Add(importResultRow.BuildStatusReport(_configuration.RepoManagerAccountUrl)); reports.Add("=====================================================================================================
"); } foreach (var importResultRow in floors) { reports.Add(importResultRow.BuildStatusReport(_configuration.RepoManagerAccountUrl)); } var result = reports.Join("
"); SendMessageAsync(_configuration.CreditDebitsRecipients, subject, result).GetAwaiter().GetResult(); Log.Debug("AutoIMS Import Email Sent"); } public void SendRefundProcessStartEmails(IReadOnlyCollection models) { if (models == null || !models.Any()) { Log.Warning("No models to process sold emails for."); return; } var soldResults = models.Where(x => x.Data?.SoldDate?.Date == DateTime.Now.Date).ToList(); foreach (var sale in soldResults) { SendMessageAsync(_configuration.CollectionsClerkRecipients, "Auction sold, please start the refund process", CreateRefundProcessEmailBody(sale)).GetAwaiter().GetResult(); } } public string CreateRefundProcessEmailBody(ImportResultRow sale) { if (sale?.RepoAccount == null || sale.Data == null || sale.RepoAccount.Borrowers == null) { Log.Error("Invalid data, can't create email body for account."); return ""; } var member = sale.RepoAccount.Borrowers?.First(b => b.OwnershipType == 6); var individualName = member != null ? member.IndividualName : "No Primary Owner!"; var memberName = "Member Name: " + individualName + "
"; var accountNo = "Account No: " + sale.RepoAccount.AccountNo + "
"; var collateralVin = "VIN: " + sale.Data.VIN + "
"; return string.Concat(memberName, accountNo, collateralVin); } public async Task SendProccessSummary(RepoRunInfo runInfo) { string subject = $"Repo Processor Run Receipt [{runInfo.Receipts.Count}]"; var receiptList = runInfo.Receipts.Select(receipt => receipt.Pretty()); string bodyData = string.Join("
", receiptList); string body = $"Process Started: {runInfo.StartDateTime} and completed at {runInfo.CompleteDateTime}

"; return await SendMessageAsync(_configuration.RepoManagerAdminRecipients, subject, body + bodyData); } } }