using Data.SeaHavenIndustries; using Microsoft.Extensions.Options; using SeaHaven.DataServices.Interfaces; using SeaHaven.Services.Configuration; using SeaHaven.Services.DTOs; using SeaHaven.Services.Interfaces; using System.Security.Cryptography; namespace SeaHaven.Services.Implementation { public class VendorPortalTokenService : IVendorPortalTokenService { private readonly IVendorDataService _vendorDataService; private readonly int _lifetimeDays; public VendorPortalTokenService(IVendorDataService vendorDataService, IOptions options) { _vendorDataService = vendorDataService; _lifetimeDays = options.Value.TokenLifetimeDays ?? 365; } public async Task GetOrCreateActiveTokenAsync(int vendorId, CancellationToken cancellationToken) { var now = DateTime.UtcNow; var existing = await _vendorDataService.GetActiveTokenForVendorAsync(vendorId, cancellationToken); if (existing != null) return MapToken(existing); var token = new VendorAccessToken { VendorId = vendorId, Token = GenerateToken(), IssuedAt = now, ExpiresAt = now.AddDays(_lifetimeDays), CreatedDate = now }; return MapToken(await _vendorDataService.AddTokenAsync(token, cancellationToken)); } public async Task ResolveSessionAsync(string? token, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(token)) return null; var now = DateTime.UtcNow; var record = await _vendorDataService.GetTokenWithVendorAsync(token, cancellationToken); if (record?.Vendor == null) return null; record.LastUsedAt = now; await _vendorDataService.SaveChangesAsync(cancellationToken); return new VendorPortalSession { Id = record.Vendor.Id, CompanyName = record.Vendor.CompanyName, ContactName = record.Vendor.ContactName, Email = record.Vendor.Email, Phone = record.Vendor.Phone }; } public async Task RotateAsync(int vendorId, CancellationToken cancellationToken) { var now = DateTime.UtcNow; var active = await _vendorDataService.GetRevocableTokensAsync(vendorId, cancellationToken); foreach (var t in active) t.RevokedAt = now; await _vendorDataService.SaveChangesAsync(cancellationToken); return await GetOrCreateActiveTokenAsync(vendorId, cancellationToken); } public async Task RevokeAllAsync(int vendorId, CancellationToken cancellationToken) { var now = DateTime.UtcNow; var active = await _vendorDataService.GetRevocableTokensAsync(vendorId, cancellationToken); foreach (var t in active) t.RevokedAt = now; await _vendorDataService.SaveChangesAsync(cancellationToken); } private static string GenerateToken() { var bytes = RandomNumberGenerator.GetBytes(32); return Convert.ToBase64String(bytes) .Replace("+", "-") .Replace("/", "_") .TrimEnd('='); } private static VendorPortalTokenStateDTO MapToken(VendorAccessToken token) => new() { Token = token.Token, IssuedAt = token.IssuedAt, ExpiresAt = token.ExpiresAt, LastUsedAt = token.LastUsedAt }; } }