using System.Net; using System.Net.Mail; using System.Text.Json; using Fitness_core_BE.Interfaces.Services; using Fitness_core_BE.Models.IOs; namespace Fitness_core_BE.Services { /// /// Combines the two outbound notification channels — SMS (Introps) and email (Gmail SMTP) — /// into one service, matching the pattern already used by Core-Hex-Auth's ThirdPartyService. /// public class ThirdPartyService : IThirdPartyService { private readonly HttpClient _httpClient; private readonly IConfiguration _config; // Email (Gmail SMTP). Use a Gmail App Password, not the account password. private readonly string _gmailUser; private readonly string _gmailPassword; private readonly string _gmailHost; private readonly int _gmailPort; private readonly string _gmailFromName; public ThirdPartyService(IHttpClientFactory httpClientFactory, IConfiguration config) { _httpClient = httpClientFactory.CreateClient(); _config = config; _gmailUser = Environment.GetEnvironmentVariable("GMAIL_USER") ?? config["Gmail:User"] ?? ""; _gmailPassword = Environment.GetEnvironmentVariable("GMAIL_APP_PASSWORD") ?? config["Gmail:AppPassword"] ?? ""; _gmailHost = config["Gmail:Host"] ?? "smtp.gmail.com"; _gmailPort = int.TryParse(config["Gmail:Port"], out var p) ? p : 587; _gmailFromName = config["Gmail:FromName"] ?? "GYM OS"; } // ---------- SMS ---------- public async Task SendSmsAsync(string mobileNumber, string? otpCode = null, string? message = null) { try { if (string.IsNullOrWhiteSpace(mobileNumber)) { return new OtpResponse { StatusCode = 400, Message = "Mobile number is required" }; } if (string.IsNullOrWhiteSpace(otpCode) && string.IsNullOrWhiteSpace(message)) { return new OtpResponse { StatusCode = 400, Message = "Either an OTP code or a message is required" }; } string contactNumber = mobileNumber; string apiUrl = _config["Sms:ApiUrl"] ?? "https://backup.introps.com/Sms_common/send_sms"; string apiKey = Environment.GetEnvironmentVariable("SMS_API_KEY") ?? _config["Sms:ApiKey"] ?? "8989898989"; var msgText = string.IsNullOrWhiteSpace(message) ? $"Your otp code is: {otpCode}" : message; var smsRequest = new SmsRequest { api_key = apiKey, phone_number = contactNumber, msg_text = msgText }; var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair("api_key", smsRequest.api_key), new KeyValuePair("phone_number", smsRequest.phone_number), new KeyValuePair("msg_text", smsRequest.msg_text) }); var response = await _httpClient.PostAsync(apiUrl, formContent); var responseContent = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode && responseContent.Contains("agent:d")) { string jsonString = responseContent.Split(new[] { "agent:d" }, StringSplitOptions.None)[1]; var responseJson = JsonSerializer.Deserialize>(jsonString); if (responseJson is not null && responseJson.TryGetValue("stt", out var statusValue) && statusValue?.ToString() == "ok") { Console.WriteLine($"SMS sent to {contactNumber}"); return new OtpResponse { StatusCode = 200, Message = "SMS sent successfully." }; } } Console.WriteLine($"Failed to send SMS to {contactNumber}. Response: {responseContent}"); return new OtpResponse { StatusCode = 500, Message = "Failed to send SMS.", ApiResponse = responseContent }; } catch (Exception ex) { Console.WriteLine($"Exception sending SMS: {ex.Message}"); return new OtpResponse { StatusCode = 500, Message = "Exception occurred while sending SMS.", Error = ex.Message }; } } // ---------- Email ---------- public async Task SendEmailAsync(string toEmail, string subject, string htmlBody, byte[]? attachment = null, string? attachmentName = null) { if (string.IsNullOrWhiteSpace(_gmailUser) || string.IsNullOrWhiteSpace(_gmailPassword)) throw new InvalidOperationException("Gmail SMTP is not configured (set GMAIL_USER / GMAIL_APP_PASSWORD)."); using var mail = new MailMessage { From = new MailAddress(_gmailUser, _gmailFromName), Subject = subject, Body = htmlBody, IsBodyHtml = true }; mail.To.Add(toEmail); MemoryStream? attachmentStream = null; if (attachment != null) { attachmentStream = new MemoryStream(attachment); mail.Attachments.Add(new Attachment(attachmentStream, attachmentName ?? "receipt.pdf", "application/pdf")); } try { using var client = new SmtpClient(_gmailHost, _gmailPort) { EnableSsl = true, Credentials = new NetworkCredential(_gmailUser, _gmailPassword) }; await client.SendMailAsync(mail); } finally { attachmentStream?.Dispose(); } } } }