using MongoDB.Bson.Serialization.Attributes; namespace GuestOps.Web; public interface ITenantDocument { string Id { get; set; } string HotelId { get; set; } } public abstract class TenantDocument : ITenantDocument { [BsonId] public string Id { get; set; } = Guid.NewGuid().ToString("N"); public string HotelId { get; set; } = ""; } public class Hotel : TenantDocument { public string AutoReplyMode {get;set;}="Off"; public string AutoReplyEpoch {get;set;}=""; public DateTime AutoReplySince {get;set;}=DateTime.UtcNow; public bool PaymentsEnabled { get; set; } public bool PmsUpdatesEnabled { get; set; } public bool AiDraftsEnabled { get; set; } public bool StaffSendingEnabled { get; set; } public string Name { get; set; } = ""; public string Timezone { get; set; } = "Europe/London"; public string Signature { get; set; } = "Warm regards,\nThe reservations team"; public string ReplyMode { get; set; } = "DraftOnly"; public long Version { get; set; } } public class StaffUser : TenantDocument { public long Version {get;set;} public string SecurityStamp {get;set;}=""; public string AccountLinkHash {get;set;}=""; public string AccountLinkPurpose {get;set;}=""; public DateTime? AccountLinkExpiresAt {get;set;} public string Email { get; set; } = ""; public string Name { get; set; } = ""; public string PasswordHash { get; set; } = ""; public string Role { get; set; } = "Owner"; public bool Active { get; set; } = true; } public class KnowledgeEntry : TenantDocument { public string Title { get; set; } = ""; public string Category { get; set; } = "General"; public string Answer { get; set; } = ""; public string Keywords { get; set; } = ""; public bool Approved { get; set; } public long Version { get; set; } } public class Conversation : TenantDocument { public bool AutoReplyHeadersEligible {get;set;} public DateTime? AutoReplyCheckedAt {get;set;} public string AutoReplyDetail {get;set;}=""; public bool AutoReplyMatched {get;set;} public string ReplyAddress { get; set; } = ""; public string RfcMessageId { get; set; } = ""; public string[] DraftSources { get; set; } = []; public string DraftReviewNote { get; set; } = ""; public Delivery? RejectedAutomaticReply {get;set;} public Delivery? Delivery { get; set; } public string MailboxId { get; set; } = ""; public string ProviderMessageId { get; set; } = ""; public string ProviderThreadId { get; set; } = ""; public string From { get; set; } = ""; public string Subject { get; set; } = ""; public string Body { get; set; } = ""; public DateTime ReceivedAt { get; set; } = DateTime.UtcNow; public string Status { get; set; } = "NeedsAttention"; public string Draft { get; set; } = ""; public string Category { get; set; } = "General"; public string Note { get; set; } = ""; public long Version { get; set; } } public class Mailbox : TenantDocument { public long Version {get;set;} public string ConnectionEpoch {get;set;}=""; public DateTime? ConnectionChangedAt {get;set;} public DateTime? LastAttemptAt {get;set;} public DateTime? NextAttemptAt {get;set;} public int FailureCount {get;set;} public string SyncErrorCode {get;set;}=""; public bool CanSend { get; set; } public string Email { get; set; } = ""; public string ProtectedRefreshToken { get; set; } = ""; public string Status { get; set; } = "Connected"; public DateTime? LastSyncAt { get; set; } public string SyncError { get; set; } = ""; public string PageToken { get; set; } = ""; public DateTime WindowStart { get; set; } = DateTime.UtcNow.AddDays(-7); public DateTime WindowEnd { get; set; } = DateTime.UtcNow; } public class OAuthRequest : TenantDocument { public DateTime StartedAt {get;set;}=DateTime.UtcNow; public string ExpectedEmail {get;set;}=""; public string UserId { get; set; } = ""; public DateTime ExpiresAt { get; set; } } public class Activity : TenantDocument { public DateTime At { get; set; } = DateTime.UtcNow; public string UserName { get; set; } = ""; public string Action { get; set; } = ""; } public class WorkerLease { [BsonId] public string Id { get; set; } = ""; public string Owner { get; set; } = ""; public DateTime Until { get; set; } } public record LoginInput(string Email, string Password); public record SettingsInput(string Name, string Timezone, string Signature, long Version); public record DraftInput(string Draft, long Version); public record StatusInput(string Status, long Version); public record KnowledgeInput(string Title, string Category, string Answer, string Keywords, bool Approved, long Version); public record VersionInput(long Version); public record SendInput(long Version, string Recipient); public record ReplyControlsInput(long Version, bool AiDraftsEnabled, bool StaffSendingEnabled); public class Delivery { public string MailboxEpoch {get;set;}=""; public bool Automatic {get;set;} public string AutoRuleId {get;set;}=""; public long AutoRuleVersion {get;set;} public string AutoKnowledgeId {get;set;}=""; public long AutoKnowledgeVersion {get;set;} public string AutoDay {get;set;}=""; public string AutoEpoch {get;set;}=""; public string Id { get; set; } = Guid.NewGuid().ToString("N"); public string State { get; set; } = "Pending"; public string Recipient { get; set; } = ""; public string Body { get; set; } = ""; public string ApprovedBy { get; set; } = ""; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; public string ProviderId { get; set; } = ""; public string Detail { get; set; } = "Awaiting delivery worker"; public string MessageId => "<" + Id + "@guestops.invalid>"; }