using JobsMedical.Web.Services.Scraping;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Hosting;
namespace JobsMedical.Web.Services;
///
/// One-time-code issuing/verification. Codes live in memory for 5 minutes. When SMS is configured
/// (admin settings) the code is sent via the gateway and NOT returned; otherwise it's returned so
/// the dev login page can display it.
///
public class OtpService
{
private readonly IMemoryCache _cache;
private readonly ISmsSender _sms;
private readonly SettingsService _settings;
private readonly IHostEnvironment _env;
public OtpService(IMemoryCache cache, ISmsSender sms, SettingsService settings, IHostEnvironment env)
{
_cache = cache;
_sms = sms;
_settings = settings;
_env = env;
}
private static string Key(string phone) => $"otp:{Normalize(phone)}";
///
/// Generate + store a 5-digit code. If SMS is enabled, send it and return null (don't reveal);
/// otherwise return the code so the dev login screen can show it.
///
public async Task IssueAsync(string phone)
{
var code = Random.Shared.Next(10000, 100000).ToString();
_cache.Set(Key(phone), code, TimeSpan.FromMinutes(5));
var settings = await _settings.GetAsync();
// In Development (local Docker / dotnet run) never call the SMS gateway — always show the
// code on the login screen. In Production, send via SMS only when it's enabled.
if (settings.SmsEnabled && !_env.IsDevelopment())
{
await _sms.SendOtpAsync(phone, code, settings);
return null; // sent via SMS — don't reveal it
}
return code; // local/dev (or SMS off): surface it on screen
}
public bool Verify(string phone, string code)
{
if (_cache.TryGetValue(Key(phone), out string? stored) && stored == code?.Trim())
{
_cache.Remove(Key(phone));
return true;
}
return false;
}
/// Normalize Iranian mobile numbers (Persian digits → Latin, strip spaces).
public static string Normalize(string phone)
{
var chars = phone.Trim().ToCharArray();
for (var i = 0; i < chars.Length; i++)
if (chars[i] >= '۰' && chars[i] <= '۹') chars[i] = (char)('0' + (chars[i] - '۰'));
return new string(chars).Replace(" ", "").Replace("-", "");
}
}