using System.Security.Cryptography; using Data.SeaHavenIndustries; using Microsoft.EntityFrameworkCore; namespace Api.SeaHavenIndustries.Helper { public class VendorPortalTokenService { private readonly ApplicationDbContext _db; private readonly int _lifetimeDays; public VendorPortalTokenService(ApplicationDbContext db, IConfiguration config) { _db = db; _lifetimeDays = config.GetValue("VendorPortal:TokenLifetimeDays") ?? 365; } public async Task GetOrCreateActiveTokenAsync(int vendorId) { var now = DateTime.UtcNow; var existing = await _db.VendorAccessTokens .Where(t => t.VendorId == vendorId && t.RevokedAt == null && t.ExpiresAt > now && (t.IsDeleted == null || t.IsDeleted == false)) .OrderByDescending(t => t.IssuedAt) .FirstOrDefaultAsync(); if (existing != null) return existing; var token = new VendorAccessToken { VendorId = vendorId, Token = GenerateToken(), IssuedAt = now, ExpiresAt = now.AddDays(_lifetimeDays), CreatedDate = now }; _db.VendorAccessTokens.Add(token); await _db.SaveChangesAsync(); return token; } public async Task ResolveVendorAsync(string? token) { if (string.IsNullOrWhiteSpace(token)) return null; var now = DateTime.UtcNow; var record = await _db.VendorAccessTokens .Include(t => t.Vendor) .FirstOrDefaultAsync(t => t.Token == token && t.RevokedAt == null && t.ExpiresAt > now && (t.IsDeleted == null || t.IsDeleted == false)); if (record?.Vendor == null) return null; record.LastUsedAt = now; await _db.SaveChangesAsync(); return record.Vendor; } public async Task RotateAsync(int vendorId) { var now = DateTime.UtcNow; var active = await _db.VendorAccessTokens .Where(t => t.VendorId == vendorId && t.RevokedAt == null) .ToListAsync(); foreach (var t in active) t.RevokedAt = now; await _db.SaveChangesAsync(); return await GetOrCreateActiveTokenAsync(vendorId); } public async Task RevokeAllAsync(int vendorId) { var now = DateTime.UtcNow; var active = await _db.VendorAccessTokens .Where(t => t.VendorId == vendorId && t.RevokedAt == null) .ToListAsync(); foreach (var t in active) t.RevokedAt = now; await _db.SaveChangesAsync(); } private static string GenerateToken() { var bytes = RandomNumberGenerator.GetBytes(32); return Convert.ToBase64String(bytes) .Replace("+", "-") .Replace("/", "_") .TrimEnd('='); } } }