using AuthApi.Models; namespace AuthApi.Services; public sealed record LegalPolicyStatus( string TermsVersion, string PrivacyVersion, DateTime EffectiveUtc, string TermsUrl, string PrivacyUrl, bool RequiresLegalAcceptance); public sealed class LegalPolicy { public const string DefaultVersion = "2026-07-20"; private readonly IConfiguration _configuration; public LegalPolicy(IConfiguration configuration) => _configuration = configuration; public string TermsVersion => _configuration["Legal:TermsVersion"] ?? DefaultVersion; public string PrivacyVersion => _configuration["Legal:PrivacyVersion"] ?? DefaultVersion; public string TermsUrl => _configuration["Legal:TermsUrl"] ?? "https://doctor.ranaze.com/terms.html"; public string PrivacyUrl => _configuration["Legal:PrivacyUrl"] ?? "https://doctor.ranaze.com/privacy.html"; public DateTime EffectiveUtc => DateTime.TryParse(_configuration["Legal:EffectiveUtc"], out var value) ? value.ToUniversalTime() : new DateTime(2026, 7, 20, 0, 0, 0, DateTimeKind.Utc); public bool IsCurrent(User user) => user.TermsAcceptedVersion == TermsVersion && user.PrivacyAcceptedVersion == PrivacyVersion; public LegalPolicyStatus Status(User? user = null) => new( TermsVersion, PrivacyVersion, EffectiveUtc, TermsUrl, PrivacyUrl, user is not null && !IsCurrent(user)); public void Accept(User user, string source, DateTime? acceptedUtc = null) { var timestamp = acceptedUtc ?? DateTime.UtcNow; user.LegalAcceptances ??= []; if (IsCurrent(user) && user.LegalAcceptances.Any(value => value.TermsVersion == TermsVersion && value.PrivacyVersion == PrivacyVersion)) return; user.TermsAcceptedVersion = TermsVersion; user.PrivacyAcceptedVersion = PrivacyVersion; user.LegalAcceptedUtc = timestamp; user.LegalAcceptances.Add(new LegalAcceptanceRecord { TermsVersion = TermsVersion, PrivacyVersion = PrivacyVersion, AcceptedUtc = timestamp, Source = source }); } }