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

namespace Tiku.Domain.Commerce;

public sealed class Product : AuditableTenantEntity
{
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public string Title { get; set; } = string.Empty;
    public string? LegacyPriceText { get; set; }
    public string? Link { get; set; }
    public ProductType Type { get; set; } = ProductType.Material;
    public JsonElement Tags { get; set; } = JsonDefaults.Array();
    public int SortOrder { get; set; }
    public string? Cover { get; set; }
    public string? PreviewIframe { get; set; }
    public JsonElement DetailImages { get; set; } = JsonDefaults.Array();
    public bool IsActive { get; set; } = true;
}

public sealed class SvipPlan : AuditableTenantEntity
{
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public string Name { get; set; } = string.Empty;
    public int PriceCents { get; set; }
    public int? OriginalPriceCents { get; set; }
    public int Days { get; set; }
    public string? Description { get; set; }
    public string? PerDayLabel { get; set; }
    public string? Badge { get; set; }
    public bool Recommended { get; set; }
    public bool CouponOnly { get; set; }
    public string? VpProductId { get; set; }
    public bool VpEnabled { get; set; }
    public int SortOrder { get; set; }
    public bool IsActive { get; set; } = true;
}

public sealed class Order : AuditableTenantEntity
{
    public Guid? UserId { get; set; }
    public Guid? PlanId { get; set; }
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public string? LegacyUserId { get; set; }
    public string? LegacyPlanId { get; set; }
    public string? LegacyRegionId { get; set; }
    public string OrderNo { get; set; } = string.Empty;
    public OrderStatus Status { get; set; } = OrderStatus.Pending;
    public string? ProductType { get; set; }
    public string? ProductName { get; set; }
    public int AmountCents { get; set; }
    public string? PayMethod { get; set; }
    public string? PayProvider { get; set; }
    public string? TradeNo { get; set; }
    public int? Days { get; set; }
    public int RefundedAmountCents { get; set; }
    public DateTimeOffset? PaidAt { get; set; }
    public JsonElement RawPayload { get; set; } = JsonDefaults.Object();
}

public sealed class OrderItem : AuditableTenantEntity
{
    public Guid OrderId { get; set; }
    public string? LegacyId { get; set; }
    public string ItemType { get; set; } = string.Empty;
    public Guid? ItemId { get; set; }
    public string Name { get; set; } = string.Empty;
    public int Quantity { get; set; } = 1;
    public int UnitAmountCents { get; set; }
    public int TotalAmountCents { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class Payment : AuditableTenantEntity
{
    public Guid OrderId { get; set; }
    public string? LegacyId { get; set; }
    public string? LegacyOrderId { get; set; }
    public string Provider { get; set; } = string.Empty;
    public string? Method { get; set; }
    public PaymentStatus Status { get; set; } = PaymentStatus.Pending;
    public int AmountCents { get; set; }
    public int RefundedAmountCents { get; set; }
    public string? ProviderTradeNo { get; set; }
    public DateTimeOffset? PaidAt { get; set; }
    public JsonElement RawPayload { get; set; } = JsonDefaults.Object();
}

public sealed class PaymentEvent : Entity, ITenantOwned
{
    public Guid? PaymentId { get; set; }
    public string Provider { get; set; } = string.Empty;
    public string EventType { get; set; } = string.Empty;
    public string? EventId { get; set; }
    public bool? SignatureValid { get; set; }
    public JsonElement Payload { get; set; } = JsonDefaults.Object();
    public DateTimeOffset? ProcessedAt { get; set; }
    public string? Error { get; set; }
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class Entitlement : Entity, ITenantOwned
{
    public Guid UserId { get; set; }
    public string EntitlementType { get; set; } = "svip";
    public EntitlementScopeType ScopeType { get; set; } = EntitlementScopeType.Tenant;
    public Guid? ScopeId { get; set; }
    public string SourceType { get; set; } = "migration";
    public Guid? SourceId { get; set; }
    public string? LegacySourceId { get; set; }
    public DateTimeOffset StartsAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset? ExpiresAt { get; set; }
    public EntitlementStatus Status { get; set; } = EntitlementStatus.Active;
    public DateTimeOffset? RevokedAt { get; set; }
    public Guid? RevokedBy { get; set; }
    public string? RevokedReason { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class CodeBatch : AuditableTenantEntity
{
    public Guid? RegionId { get; set; }
    public Guid? CreatedBy { get; set; }
    public string? LegacyId { get; set; }
    public string Name { get; set; } = string.Empty;
    public string? SaleType { get; set; }
    public string? Channel { get; set; }
    public string? CampaignName { get; set; }
    public int DefaultUnitPriceCents { get; set; }
    public int CostPriceCents { get; set; }
    public int TotalCount { get; set; }
    public int? Days { get; set; }
    public string? LegacyRegionId { get; set; }
    public DateTimeOffset? IssuedAt { get; set; }
    public string? Remark { get; set; }
    public decimal? CommissionRate { get; set; }
}

public sealed class ActivationCode : AuditableTenantEntity
{
    public Guid? UsedBy { get; set; }
    public Guid? AgentUserId { get; set; }
    public Guid? BatchId { get; set; }
    public Guid? UsedRegionId { get; set; }
    public Guid? CouponRedemptionId { get; set; }
    public string? LegacyId { get; set; }
    public string Code { get; set; } = string.Empty;
    public int Days { get; set; }
    public bool IsUsed { get; set; }
    public DateTimeOffset? UsedAt { get; set; }
    public string? SaleType { get; set; }
    public int? UnitPriceCents { get; set; }
    public string? SoldTo { get; set; }
    public string? CouponCode { get; set; }
    public string? Remark { get; set; }
}

public sealed class Coupon : AuditableTenantEntity
{
    public Guid? PlanId { get; set; }
    public string? LegacyId { get; set; }
    public string Code { get; set; } = string.Empty;
    public DiscountType? DiscountType { get; set; }
    public decimal? DiscountValue { get; set; }
    public DateTimeOffset? ValidFrom { get; set; }
    public DateTimeOffset? ValidTo { get; set; }
    public int? MaxUses { get; set; }
    public int UsedCount { get; set; }
    public string? Source { get; set; }
    public string? Remark { get; set; }
}

public sealed class CouponRedemption : AuditableTenantEntity
{
    public Guid? CouponId { get; set; }
    public Guid? UserId { get; set; }
    public Guid? PlanId { get; set; }
    public Guid? OrderId { get; set; }
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public string? CouponCode { get; set; }
    public CouponRedemptionStatus Status { get; set; } = CouponRedemptionStatus.Claimed;
    public int? DiscountAppliedCents { get; set; }
    public string? Source { get; set; }
    public string? Remark { get; set; }
    public DateTimeOffset? ClaimedAt { get; set; }
    public DateTimeOffset? UsedAt { get; set; }
}

public sealed class CommerceRefundRequest : AuditableTenantEntity
{
    public Guid OrderId { get; set; }
    public Guid? PaymentId { get; set; }
    public Guid? RequestedBy { get; set; }
    public Guid? ReviewedBy { get; set; }
    public Guid? ProcessedBy { get; set; }
    public string RefundNo { get; set; } = string.Empty;
    public string? Provider { get; set; }
    public string? ProviderRefundNo { get; set; }
    public CommerceRefundStatus Status { get; set; } = CommerceRefundStatus.Requested;
    public int AmountCents { get; set; }
    public string? Reason { get; set; }
    public RefundEntitlementAction EntitlementAction { get; set; } = RefundEntitlementAction.RevokeOnSuccess;
    public DateTimeOffset RequestedAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset? ReviewedAt { get; set; }
    public DateTimeOffset? ProcessedAt { get; set; }
    public DateTimeOffset? SucceededAt { get; set; }
    public DateTimeOffset? FailedAt { get; set; }
    public DateTimeOffset? CancelledAt { get; set; }
    public string? FailureReason { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class CommerceRefundEvent : Entity, ITenantOwned
{
    public Guid RefundRequestId { get; set; }
    public CommerceRefundStatus? FromStatus { get; set; }
    public CommerceRefundStatus ToStatus { get; set; } = CommerceRefundStatus.Requested;
    public string EventType { get; set; } = string.Empty;
    public Guid? ActorUserId { get; set; }
    public JsonElement Details { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class CommerceReconciliationBatch : AuditableTenantEntity
{
    public Guid? CreatedBy { get; set; }
    public string Provider { get; set; } = string.Empty;
    public DateOnly BillDate { get; set; }
    public ReconciliationBillType BillType { get; set; } = ReconciliationBillType.Combined;
    public ReconciliationSource Source { get; set; } = ReconciliationSource.ManualUpload;
    public string? SourceName { get; set; }
    public string SourceHash { get; set; } = string.Empty;
    public ReconciliationBatchStatus Status { get; set; } = ReconciliationBatchStatus.Completed;
    public int TotalCount { get; set; }
    public int MatchedCount { get; set; }
    public int MismatchCount { get; set; }
    public int MissingLocalCount { get; set; }
    public int MissingProviderCount { get; set; }
    public int DuplicateCount { get; set; }
    public int IgnoredCount { get; set; }
    public int AmountCents { get; set; }
    public int RefundAmountCents { get; set; }
    public int FeeCents { get; set; }
    public DateTimeOffset? CompletedAt { get; set; }
    public string? Error { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class CommerceReconciliationItem : Entity, ITenantOwned
{
    public Guid BatchId { get; set; }
    public Guid? OrderId { get; set; }
    public Guid? PaymentId { get; set; }
    public Guid? RefundRequestId { get; set; }
    public int RowNo { get; set; }
    public string Provider { get; set; } = string.Empty;
    public ReconciliationTransactionType TransactionType { get; set; } = ReconciliationTransactionType.Payment;
    public string? ProviderTradeNo { get; set; }
    public string? ProviderRefundNo { get; set; }
    public string? OrderNo { get; set; }
    public string? RefundNo { get; set; }
    public int AmountCents { get; set; }
    public int RefundAmountCents { get; set; }
    public int FeeCents { get; set; }
    public DateTimeOffset? PaidAt { get; set; }
    public DateTimeOffset? RefundedAt { get; set; }
    public string? ProviderStatus { get; set; }
    public string? LocalStatus { get; set; }
    public ReconciliationMatchStatus MatchStatus { get; set; } = ReconciliationMatchStatus.Matched;
    public NotificationSeverity Severity { get; set; } = NotificationSeverity.Info;
    public string? IssueCode { get; set; }
    public JsonElement Details { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class CommerceReconciliationIssue : AuditableTenantEntity
{
    public Guid? BatchId { get; set; }
    public Guid? ItemId { get; set; }
    public Guid? OrderId { get; set; }
    public Guid? PaymentId { get; set; }
    public Guid? RefundRequestId { get; set; }
    public Guid? AssignedTo { get; set; }
    public Guid? CreatedBy { get; set; }
    public Guid? ResolvedBy { get; set; }
    public string IssueNo { get; set; } = string.Empty;
    public string Provider { get; set; } = string.Empty;
    public ReconciliationTransactionType TransactionType { get; set; } = ReconciliationTransactionType.Payment;
    public string? IssueCode { get; set; }
    public ReconciliationIssueMatchStatus MatchStatus { get; set; } = ReconciliationIssueMatchStatus.AmountMismatch;
    public NotificationSeverity Severity { get; set; } = NotificationSeverity.Warning;
    public ReconciliationIssueStatus Status { get; set; } = ReconciliationIssueStatus.Open;
    public ReconciliationResolutionType ResolutionType { get; set; } = ReconciliationResolutionType.None;
    public string? OrderNo { get; set; }
    public string? RefundNo { get; set; }
    public string? ProviderTradeNo { get; set; }
    public string? ProviderRefundNo { get; set; }
    public int AmountCents { get; set; }
    public int RefundAmountCents { get; set; }
    public DateTimeOffset? ResolvedAt { get; set; }
    public DateTimeOffset? DueAt { get; set; }
    public string? Summary { get; set; }
    public string? ResolutionNote { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class CommerceReconciliationIssueEvent : Entity, ITenantOwned
{
    public Guid IssueId { get; set; }
    public ReconciliationIssueStatus? FromStatus { get; set; }
    public ReconciliationIssueStatus? ToStatus { get; set; }
    public string EventType { get; set; } = string.Empty;
    public Guid? ActorUserId { get; set; }
    public string? Note { get; set; }
    public JsonElement Details { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class CommerceAdjustmentVoucher : AuditableTenantEntity
{
    public Guid? IssueId { get; set; }
    public Guid? BatchId { get; set; }
    public Guid? ItemId { get; set; }
    public Guid? OrderId { get; set; }
    public Guid? PaymentId { get; set; }
    public Guid? RefundRequestId { get; set; }
    public Guid? CreatedBy { get; set; }
    public Guid? ReviewedBy { get; set; }
    public string VoucherNo { get; set; } = string.Empty;
    public CommerceAdjustmentVoucherStatus Status { get; set; } = CommerceAdjustmentVoucherStatus.Draft;
    public CommerceAdjustmentDirection Direction { get; set; } = CommerceAdjustmentDirection.IncreaseRevenue;
    public int AmountCents { get; set; }
    public string Currency { get; set; } = "CNY";
    public string Reason { get; set; } = string.Empty;
    public string? ProofAssetKey { get; set; }
    public DateTimeOffset? ReviewedAt { get; set; }
    public DateTimeOffset? ClosedAt { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class CommerceAdjustmentVoucherEvent : Entity, ITenantOwned
{
    public Guid VoucherId { get; set; }
    public CommerceAdjustmentVoucherStatus? FromStatus { get; set; }
    public CommerceAdjustmentVoucherStatus ToStatus { get; set; } = CommerceAdjustmentVoucherStatus.Draft;
    public Guid? ActorUserId { get; set; }
    public string? Note { get; set; }
    public JsonElement Details { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public enum ProductType
{
    Material,
    Course,
    Service,
    Link,
    Other
}

public enum OrderStatus
{
    Pending,
    Paid,
    Failed,
    Closed,
    PartiallyRefunded,
    Refunded
}

public enum PaymentStatus
{
    Pending,
    Paid,
    Failed,
    Cancelled,
    PartiallyRefunded,
    Refunded
}

public enum EntitlementScopeType
{
    Tenant,
    Region,
    Module,
    Subject,
    QuestionBank
}

public enum EntitlementStatus
{
    Active,
    Revoked,
    Expired
}

public enum DiscountType
{
    Percent,
    Fixed
}

public enum CouponRedemptionStatus
{
    Claimed,
    Used,
    Expired,
    Cancelled
}

public enum CommerceRefundStatus
{
    Requested,
    Approved,
    Processing,
    Succeeded,
    Failed,
    Rejected,
    Cancelled
}

public enum RefundEntitlementAction
{
    None,
    RevokeOnSuccess
}

public enum ReconciliationBillType
{
    Payment,
    Refund,
    Combined
}

public enum ReconciliationSource
{
    ManualUpload,
    ProviderDownload,
    Api,
    Worker
}

public enum ReconciliationBatchStatus
{
    Preview,
    Pending,
    Processing,
    Completed,
    CompletedWithIssues,
    Failed
}

public enum ReconciliationTransactionType
{
    Payment,
    Refund
}

public enum ReconciliationMatchStatus
{
    Matched,
    AmountMismatch,
    StatusMismatch,
    MissingLocal,
    MissingProvider,
    Duplicate,
    Ignored
}

public enum ReconciliationIssueMatchStatus
{
    AmountMismatch,
    StatusMismatch,
    MissingLocal,
    MissingProvider,
    Duplicate
}

public enum NotificationSeverity
{
    Info,
    Warning,
    Error,
    Critical
}

public enum ReconciliationIssueStatus
{
    Open,
    Investigating,
    Resolved,
    Ignored,
    Escalated
}

public enum ReconciliationResolutionType
{
    None,
    ProviderConfirmed,
    LocalCorrected,
    ManualAdjustment,
    FalsePositive,
    Duplicate,
    WriteOff
}

public enum CommerceAdjustmentVoucherStatus
{
    Draft,
    PendingReview,
    Approved,
    Rejected,
    Closed,
    Void
}

public enum CommerceAdjustmentDirection
{
    IncreaseRevenue,
    DecreaseRevenue,
    IncreaseRefund,
    DecreaseRefund,
    WriteOff
}