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();
}
}
}
}