using System.ComponentModel.DataAnnotations; using System.Text.Json; using Tiku.Application.PlatformAdmin; using Tiku.Domain.Common; using Tiku.Domain.Commerce; using Tiku.Domain.Identity; using Tiku.Domain.Platform; using Tiku.Domain.Tenancy; namespace Tiku.Api.Contracts; public sealed class PlatformAdminQueryDto { [StringLength(32)] public string? Status { get; set; } [StringLength(200)] public string? Search { get; set; } [Range(1, 200)] public int? Limit { get; set; } public PlatformAdminQuery ToQuery() => new(Status, Search, Limit); } public sealed class CreatePlatformTenantDto { [Required] [StringLength(100)] public string Slug { get; set; } = string.Empty; [Required] [StringLength(200)] public string Name { get; set; } = string.Empty; [StringLength(300)] public string? LegalName { get; set; } public TenantStatus Status { get; set; } = TenantStatus.Active; public BillingStatus BillingStatus { get; set; } = BillingStatus.Trial; public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public CreatePlatformTenantCommand ToCommand() => new(Slug, Name, LegalName, Status, BillingStatus, Metadata); } public sealed class UpdatePlatformTenantStatusDto { [Required] public Guid TenantId { get; set; } public TenantStatus Status { get; set; } = TenantStatus.Active; public BillingStatus BillingStatus { get; set; } = BillingStatus.Active; [StringLength(1000)] public string? Reason { get; set; } public UpdatePlatformTenantStatusCommand ToCommand() => new(TenantId, Status, BillingStatus, Reason); } public sealed class UpsertPlatformTenantBillingProfileDto { [Required] public Guid TenantId { get; set; } [StringLength(300)] public string? BillingName { get; set; } [StringLength(100)] public string? TaxId { get; set; } [StringLength(100)] public string? ContactName { get; set; } [StringLength(32)] public string? ContactPhone { get; set; } [StringLength(320)] public string? ContactEmail { get; set; } [StringLength(1000)] public string? BillingAddress { get; set; } [StringLength(300)] public string? InvoiceTitle { get; set; } public TenantInvoiceTitleType? InvoiceType { get; set; } [StringLength(300)] public string? BankName { get; set; } [StringLength(100)] public string? BankAccountMasked { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertPlatformTenantBillingProfileCommand ToCommand() => new( TenantId, BillingName, TaxId, ContactName, ContactPhone, ContactEmail, BillingAddress, InvoiceTitle, InvoiceType, BankName, BankAccountMasked, Metadata); } public sealed class UpsertPlatformSubscriptionDto { [Required] public Guid TenantId { get; set; } [Required] [StringLength(100)] public string PlanCode { get; set; } = string.Empty; public TenantSubscriptionStatus Status { get; set; } = TenantSubscriptionStatus.Active; public DateTimeOffset? StartsAt { get; set; } public DateTimeOffset? ExpiresAt { get; set; } [StringLength(32)] public string? BillingCycle { get; set; } [Range(0, int.MaxValue)] public int AmountCents { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertPlatformSubscriptionCommand ToCommand() => new( TenantId, PlanCode, Status, StartsAt, ExpiresAt, BillingCycle, AmountCents, Metadata); } public sealed class UpsertPlatformStaffDto { public Guid? UserId { get; set; } [StringLength(320)] public string? Email { get; set; } [StringLength(32)] public string? Phone { get; set; } [StringLength(200)] public string? Name { get; set; } public UserStatus Status { get; set; } = UserStatus.Active; public IReadOnlyCollection RoleIds { get; set; } = []; public UpsertPlatformStaffCommand ToCommand() => new(UserId, Email, Phone, Name, Status, RoleIds); } public sealed class UpdatePlatformStaffStatusDto { [Required] public Guid UserId { get; set; } public UserStatus Status { get; set; } = UserStatus.Active; [StringLength(1000)] public string? Reason { get; set; } public UpdatePlatformStaffStatusCommand ToCommand() => new(UserId, Status, Reason); } public sealed class UpdatePlatformAuditAlertStatusDto { [Required] public Guid AlertId { get; set; } public PlatformAuditAlertStatus Status { get; set; } = PlatformAuditAlertStatus.Acknowledged; [StringLength(1000)] public string? ResolutionNote { get; set; } public UpdatePlatformAuditAlertStatusCommand ToCommand() => new(AlertId, Status, ResolutionNote); } public sealed class UpsertPlatformDunningChannelDto { public Guid? ChannelId { get; set; } [Required] [StringLength(100)] public string ChannelCode { get; set; } = string.Empty; [Required] [StringLength(200)] public string Name { get; set; } = string.Empty; [StringLength(1000)] public string? Description { get; set; } public bool Enabled { get; set; } = true; public PlatformDunningProvider Provider { get; set; } = PlatformDunningProvider.Generic; [Required] [StringLength(2048)] public string WebhookUrl { get; set; } = string.Empty; [StringLength(300)] public string? SecretRef { get; set; } public IReadOnlyCollection ReminderTypes { get; set; } = ["overdue", "final_notice"]; public IReadOnlyCollection ReminderChannels { get; set; } = ["internal"]; [Range(1, 20)] public int MinReminderLevel { get; set; } = 1; public IReadOnlyCollection TenantIds { get; set; } = []; [Range(1, 60)] public int TimeoutSeconds { get; set; } = 10; public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertPlatformDunningChannelCommand ToCommand() => new( ChannelId, ChannelCode, Name, Description, Enabled, Provider, WebhookUrl, SecretRef, ReminderTypes, ReminderChannels, MinReminderLevel, TenantIds, TimeoutSeconds, Metadata); } public sealed class DisablePlatformDunningChannelDto { [Required] public Guid ChannelId { get; set; } [StringLength(1000)] public string? Reason { get; set; } public DisablePlatformDunningChannelCommand ToCommand() => new(ChannelId, Reason); } public sealed class RetryPlatformDunningEventDto { [Required] public Guid EventId { get; set; } [StringLength(1000)] public string? Reason { get; set; } public RetryPlatformDunningEventCommand ToCommand() => new(EventId, Reason); }