using System.Text.Json;
using Tiku.Domain.Common;

namespace Tiku.Domain.Platform;

public sealed class PlatformSaasPlan : AuditableEntity
{
    public string Code { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public PlatformBillingCycle BillingCycle { get; set; } = PlatformBillingCycle.Yearly;
    public int BaseAmountCents { get; set; }
    public string Currency { get; set; } = "CNY";
    public JsonElement IncludedQuotas { get; set; } = JsonDefaults.Object();
    public JsonElement OveragePrices { get; set; } = JsonDefaults.Object();
    public JsonElement FeatureFlags { get; set; } = JsonDefaults.Object();
    public PlatformSaasPlanStatus Status { get; set; } = PlatformSaasPlanStatus.Active;
    public int SortOrder { get; set; }
}

public sealed class ProductModule : AuditableEntity
{
    public string Code { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public ProductModuleStatus Status { get; set; } = ProductModuleStatus.Active;
    public int SortOrder { get; set; }
}

public sealed class PlanModuleEntitlement : Entity
{
    public string PlanCode { get; set; } = string.Empty;
    public string ModuleCode { get; set; } = string.Empty;
    public bool Enabled { get; set; } = true;
}

public sealed class TenantModuleOverride : AuditableTenantEntity
{
    public string ModuleCode { get; set; } = string.Empty;
    public TenantModuleOverrideMode Mode { get; set; } = TenantModuleOverrideMode.Disabled;
    public DateTimeOffset? ExpiresAt { get; set; }
    public string? Reason { get; set; }
}

public sealed class TenantBillingProfile : IHasTimestamps, ITenantOwned
{
    public Guid TenantId { get; set; }
    public string? BillingName { get; set; }
    public string? TaxId { get; set; }
    public string? ContactName { get; set; }
    public string? ContactPhone { get; set; }
    public string? ContactEmail { get; set; }
    public string? BillingAddress { get; set; }
    public string? InvoiceTitle { get; set; }
    public TenantInvoiceTitleType? InvoiceType { get; set; }
    public string? BankName { get; set; }
    public string? BankAccountMasked { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
}

public sealed class TenantInvoice : AuditableTenantEntity
{
    public Guid? CreatedBy { get; set; }
    public string InvoiceNo { get; set; } = string.Empty;
    public TenantInvoiceType InvoiceType { get; set; } = TenantInvoiceType.Subscription;
    public TenantInvoiceStatus Status { get; set; } = TenantInvoiceStatus.Draft;
    public string Currency { get; set; } = "CNY";
    public int SubtotalCents { get; set; }
    public int DiscountCents { get; set; }
    public int TaxCents { get; set; }
    public int TotalCents { get; set; }
    public int PaidCents { get; set; }
    public int BalanceCents { get; set; }
    public DateOnly? BillingPeriodStart { get; set; }
    public DateOnly? BillingPeriodEnd { get; set; }
    public DateOnly? DueDate { get; set; }
    public DateTimeOffset? IssuedAt { get; set; }
    public DateTimeOffset? PaidAt { get; set; }
    public string? Note { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class TenantInvoiceItem : Entity, ITenantOwned
{
    public Guid TenantId { get; set; }
    public Guid InvoiceId { get; set; }
    public string ItemType { get; set; } = "subscription";
    public Guid? ItemRefId { get; set; }
    public string Description { get; set; } = string.Empty;
    public decimal Quantity { get; set; } = 1;
    public int UnitAmountCents { get; set; }
    public int AmountCents { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}

public sealed class TenantInvoicePayment : AuditableTenantEntity
{
    public Guid InvoiceId { get; set; }
    public Guid? ReceivedBy { get; set; }
    public string PaymentNo { get; set; } = string.Empty;
    public string Provider { get; set; } = "manual";
    public string? Method { get; set; }
    public TenantInvoicePaymentStatus Status { get; set; } = TenantInvoicePaymentStatus.Paid;
    public int AmountCents { get; set; }
    public DateTimeOffset? PaidAt { get; set; }
    public string? ProviderTradeNo { get; set; }
    public JsonElement RawPayload { get; set; } = JsonDefaults.Object();
}

public sealed class TenantInvoiceReminder : AuditableTenantEntity
{
    public Guid InvoiceId { get; set; }
    public Guid? CreatedBy { get; set; }
    public TenantInvoiceReminderType ReminderType { get; set; } = TenantInvoiceReminderType.Overdue;
    public TenantInvoiceReminderChannel Channel { get; set; } = TenantInvoiceReminderChannel.Manual;
    public TenantInvoiceReminderStatus Status { get; set; } = TenantInvoiceReminderStatus.Pending;
    public DateOnly ReminderDate { get; set; }
    public int ReminderLevel { get; set; } = 1;
    public DateOnly? DueDate { get; set; }
    public int BalanceCentsSnapshot { get; set; }
    public string? Message { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset? SentAt { get; set; }
    public DateTimeOffset? AcknowledgedAt { get; set; }
}

public sealed class PlatformAuditAlertRule : AuditableEntity
{
    public Guid? TenantId { get; set; }
    public string Code { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public bool Enabled { get; set; } = true;
    public PlatformAlertSeverity Severity { get; set; } = PlatformAlertSeverity.Medium;
    public string[] ActionPatterns { get; set; } = [];
    public string[] TargetTypes { get; set; } = [];
    public JsonElement Conditions { get; set; } = JsonDefaults.Object();
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class PlatformAuditAlert : AuditableEntity
{
    public Guid RuleId { get; set; }
    public Guid AuditLogId { get; set; }
    public Guid? TenantId { get; set; }
    public Guid? AcknowledgedBy { get; set; }
    public Guid? ResolvedBy { get; set; }
    public PlatformAlertSeverity Severity { get; set; } = PlatformAlertSeverity.Medium;
    public PlatformAuditAlertStatus Status { get; set; } = PlatformAuditAlertStatus.Open;
    public string Action { get; set; } = string.Empty;
    public string? TargetType { get; set; }
    public string? TargetId { get; set; }
    public string Title { get; set; } = string.Empty;
    public string? Summary { get; set; }
    public JsonElement Details { get; set; } = JsonDefaults.Object();
    public DateTimeOffset FirstSeenAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset LastSeenAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset? AcknowledgedAt { get; set; }
    public DateTimeOffset? ResolvedAt { get; set; }
    public string? ResolutionNote { get; set; }
}

public sealed class PlatformDunningNotificationChannel : AuditableEntity
{
    public string ChannelCode { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public bool Enabled { get; set; } = true;
    public PlatformDunningProvider Provider { get; set; } = PlatformDunningProvider.Generic;
    public string WebhookUrl { get; set; } = string.Empty;
    public string? SecretRef { get; set; }
    public string[] ReminderTypes { get; set; } = ["overdue", "final_notice"];
    public string[] ReminderChannels { get; set; } = ["internal"];
    public int MinReminderLevel { get; set; } = 1;
    public Guid[] TenantIds { get; set; } = [];
    public int TimeoutSeconds { get; set; } = 10;
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class PlatformDunningNotificationEvent : AuditableTenantEntity
{
    public Guid ChannelId { get; set; }
    public Guid ReminderId { get; set; }
    public Guid InvoiceId { get; set; }
    public PlatformDunningProvider Provider { get; set; } = PlatformDunningProvider.Generic;
    public PlatformDunningNotificationStatus Status { get; set; } = PlatformDunningNotificationStatus.Pending;
    public int Attempts { get; set; }
    public DateTimeOffset ScheduledAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset? NextAttemptAt { get; set; }
    public DateTimeOffset? LastAttemptAt { get; set; }
    public DateTimeOffset? SentAt { get; set; }
    public string? LastError { get; set; }
    public int? LastHttpCode { get; set; }
    public string? LastResponseSummary { get; set; }
    public JsonElement RequestPayload { get; set; } = JsonDefaults.Object();
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public enum PlatformBillingCycle { Monthly, Quarterly, Yearly, OneTime }
public enum PlatformSaasPlanStatus { Active, Archived }
public enum ProductModuleStatus { Active, Archived }
public enum TenantModuleOverrideMode { Enabled, Disabled }
public enum TenantInvoiceTitleType { None, NormalVat, SpecialVat }
public enum TenantInvoiceType { Subscription, ServiceFee, UsageOverage, ManualAdjustment }
public enum TenantInvoiceStatus { Draft, Issued, Paid, Void, Overdue }
public enum TenantInvoicePaymentStatus { Pending, Paid, Failed, Refunded }
public enum TenantInvoiceReminderType { DueSoon, Overdue, FinalNotice, Manual }
public enum TenantInvoiceReminderChannel { Manual, Internal, Sms, Email, Wechat, Crm }
public enum TenantInvoiceReminderStatus { Pending, Sent, Acknowledged, Dismissed, Failed }
public enum PlatformAlertSeverity { Low, Medium, High, Critical }
public enum PlatformAuditAlertStatus { Open, Acknowledged, Resolved, Ignored }
public enum PlatformDunningProvider { Generic, Dingtalk, Feishu, Wecom }
public enum PlatformDunningNotificationStatus { Pending, Processing, Sent, Retrying, Failed, Discarded }
