using System.Text.Json;
using Tiku.Application.Jobs;
using Tiku.Domain.Commerce;
using Tiku.Domain.Tenancy;

namespace Tiku.Application.Commerce;

public sealed record CommerceAdminActor(Guid TenantId, Guid UserId);

public sealed record CommerceAdminQuery(string? Provider = null, string? Status = null, int? Limit = null);

public sealed record TenantPointQuery(
    string? Status = null,
    int? Limit = null,
    Guid? UserId = null,
    Guid? RegionId = null);

public sealed record UpsertPaymentAccountCommand(
    string Provider,
    string? Mode,
    string? DisplayName,
    TenantExternalProviderStatus Status,
    string? SecretRef,
    int? Priority,
    JsonElement ConfigPublic);

public sealed record TenantPaymentProviderItem(
    Guid Id,
    string Provider,
    string Mode,
    string? DisplayName,
    TenantExternalProviderStatus Status,
    string? SecretRef,
    int Priority,
    JsonElement ConfigPublic,
    DateTimeOffset CreatedAt,
    DateTimeOffset UpdatedAt);

public sealed record UpsertTenantSecretCommand(
    string Purpose,
    string Provider,
    string SecretKey,
    string SecretRef,
    TenantSecretStatus Status,
    JsonElement SecretPayload,
    DateTimeOffset? ExpiresAt);

public sealed record TenantSecretItem(
    Guid Id,
    string Purpose,
    string Provider,
    string SecretKey,
    string SecretRef,
    string Status,
    DateTimeOffset? RotatedAt,
    DateTimeOffset? ExpiresAt,
    DateTimeOffset UpdatedAt);

public sealed record AdminOrderList(IReadOnlyCollection<CommerceOrderItem> Items);

public sealed record AdminPaymentList(IReadOnlyCollection<CommercePaymentItem> Items);

public sealed record CreateCodeBatchCommand(
    string Name,
    int TotalCount,
    int Days,
    Guid? RegionId,
    string? SaleType,
    string? Channel,
    int? DefaultUnitPriceCents,
    int? CostPriceCents,
    string? Remark);

public sealed record CodeBatchItem(
    Guid Id,
    string Name,
    int TotalCount,
    int Days,
    Guid? RegionId,
    string? SaleType,
    string? Channel,
    int DefaultUnitPriceCents,
    int CostPriceCents,
    DateTimeOffset? IssuedAt,
    string? Remark,
    DateTimeOffset CreatedAt);

public sealed record ActivationCodeItem(
    Guid Id,
    Guid? BatchId,
    string Code,
    int Days,
    bool IsUsed,
    Guid? UsedBy,
    DateTimeOffset? UsedAt,
    string? SaleType,
    string? SoldTo,
    string? Remark,
    DateTimeOffset CreatedAt);

public sealed record ActivationCodeList(IReadOnlyCollection<ActivationCodeItem> Items);

public sealed record RedeemActivationCodeCommand(string Code, Guid UserId, Guid? RegionId);

public sealed record UpsertPointTaskCommand(
    Guid? Id,
    string TaskKey,
    string Title,
    string? Description,
    PointActivityTaskType TaskType,
    PointActivityTaskStatus Status,
    int Points,
    int MaxClaimsPerUser,
    DateTimeOffset? StartsAt,
    DateTimeOffset? EndsAt,
    int SortOrder,
    JsonElement Rules,
    JsonElement Metadata);

public sealed record UpsertPointExchangeItemCommand(
    Guid? Id,
    Guid? RegionId,
    string ItemKey,
    string Name,
    string? Description,
    PointExchangeItemType ItemType,
    PointExchangeItemStatus Status,
    int PointsCost,
    int? Stock,
    int? Days,
    int SortOrder,
    DateTimeOffset? StartsAt,
    DateTimeOffset? EndsAt,
    JsonElement FulfillmentPayload,
    JsonElement Metadata);

public sealed record UpdatePointExchangeOrderStatusCommand(Guid OrderId, PointExchangeOrderStatus Status);

public sealed record TenantPointTaskList(IReadOnlyCollection<PointActivityTask> Items);

public sealed record TenantPointClaimList(IReadOnlyCollection<PointActivityClaim> Items);

public sealed record TenantPointExchangeItemList(IReadOnlyCollection<PointExchangeItem> Items);

public sealed record TenantPointExchangeOrderList(IReadOnlyCollection<PointExchangeOrder> Items);

public sealed record UpsertCouponCommand(
    Guid? Id,
    string Code,
    Guid? PlanId,
    DiscountType DiscountType,
    decimal DiscountValue,
    DateTimeOffset? ValidFrom,
    DateTimeOffset? ValidTo,
    int? MaxUses,
    string? Source,
    string? Remark);

public sealed record TenantCouponList(IReadOnlyCollection<Coupon> Items);

public sealed record TenantCouponRedemptionList(IReadOnlyCollection<CouponRedemption> Items);

public sealed record TenantCouponReport(int CouponCount, int ClaimedCount, int UsedCount, int DiscountAppliedCents);

public sealed record CreateRefundRequestCommand(
    Guid OrderId,
    Guid? PaymentId,
    int AmountCents,
    string? Reason,
    RefundEntitlementAction EntitlementAction,
    JsonElement Metadata);

public sealed record UpdateRefundStatusCommand(
    Guid RefundRequestId,
    CommerceRefundStatus Status,
    string? Reason = null,
    string? ProviderRefundNo = null);

public sealed record TenantRefundList(IReadOnlyCollection<CommerceRefundRequest> Items);

public sealed record TenantRefundEventList(IReadOnlyCollection<CommerceRefundEvent> Items);

public sealed record CreateReconciliationBatchCommand(
    string Provider,
    DateOnly BillDate,
    ReconciliationBillType BillType,
    ReconciliationSource Source,
    string? SourceName,
    string SourceHash,
    JsonElement Metadata);

public sealed record TenantReconciliationBatchList(IReadOnlyCollection<CommerceReconciliationBatch> Items);

public sealed record TenantReconciliationIssueList(IReadOnlyCollection<CommerceReconciliationIssue> Items);

public sealed record TenantReconciliationItemList(IReadOnlyCollection<CommerceReconciliationItem> Items);

public sealed record TenantReconciliationIssueEventList(IReadOnlyCollection<CommerceReconciliationIssueEvent> Items);

public sealed record TenantCommerceAnomalySummary(
    int OpenRefundCount,
    int ProcessingRefundCount,
    int OpenReconciliationIssueCount,
    int FailedReconciliationBatchCount,
    int PendingPaymentCount,
    int PaymentMismatchCount);

public sealed record CreateAdjustmentVoucherCommand(
    Guid? IssueId,
    Guid? BatchId,
    Guid? ItemId,
    Guid? OrderId,
    Guid? PaymentId,
    Guid? RefundRequestId,
    CommerceAdjustmentDirection Direction,
    int AmountCents,
    string? Currency,
    string Reason,
    string? ProofAssetKey,
    JsonElement Metadata);

public sealed record UpdateAdjustmentVoucherStatusCommand(
    Guid VoucherId,
    CommerceAdjustmentVoucherStatus Status,
    string? Note);

public sealed record TenantAdjustmentVoucherList(IReadOnlyCollection<CommerceAdjustmentVoucher> Items);

public sealed record TenantAdjustmentVoucherEventList(IReadOnlyCollection<CommerceAdjustmentVoucherEvent> Items);

public sealed record TenantAdjustmentReport(
    int DraftCount,
    int PendingReviewCount,
    int ApprovedCount,
    int ClosedCount,
    int IncreaseRevenueCents,
    int DecreaseRevenueCents);

public sealed record PreviewReconciliationImportCommand(
    string Provider,
    DateOnly BillDate,
    ReconciliationBillType BillType,
    string SourceName,
    JsonElement Rows);

public sealed record ReconciliationImportPreview(
    int TotalCount,
    int PaymentCount,
    int RefundCount,
    int InvalidCount,
    int AmountCents,
    int RefundAmountCents,
    string SourceHash);

public sealed record ImportReconciliationCommand(
    string Provider,
    DateOnly BillDate,
    ReconciliationBillType BillType,
    string SourceName,
    JsonElement Rows);

public sealed record RequestProviderBillJobCommand(
    string Provider,
    DateOnly BillDate,
    ReconciliationBillType BillType,
    DateTimeOffset? RunAfter = null);

public sealed record RefundNotificationCommand(
    string Provider,
    string RefundNo,
    string? ProviderRefundNo,
    CommerceRefundStatus Status,
    string? EventId,
    JsonElement Payload);

public sealed record UpdateReconciliationIssueCommand(
    Guid IssueId,
    ReconciliationIssueStatus Status,
    ReconciliationResolutionType ResolutionType,
    string? Note,
    Guid? AssignedTo = null);

public interface ICommerceAdminService
{
    Task<IReadOnlyCollection<TenantPaymentProviderItem>> GetPaymentAccountsAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<TenantPaymentProviderItem> UpsertPaymentAccountAsync(
        CommerceAdminActor actor,
        UpsertPaymentAccountCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantSecretItem> UpsertTenantSecretAsync(
        CommerceAdminActor actor,
        UpsertTenantSecretCommand command,
        CancellationToken cancellationToken = default);

    Task<AdminOrderList> GetOrdersAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<AdminPaymentList> GetPaymentsAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<CodeBatchItem> CreateCodeBatchAsync(
        CommerceAdminActor actor,
        CreateCodeBatchCommand command,
        CancellationToken cancellationToken = default);

    Task<ActivationCodeList> GetActivationCodesAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<ActivationCodeItem> RedeemActivationCodeAsync(
        CommerceAdminActor actor,
        RedeemActivationCodeCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantPointTaskList> GetPointTasksAsync(
        CommerceAdminActor actor,
        TenantPointQuery query,
        CancellationToken cancellationToken = default);

    Task<PointActivityTask> UpsertPointTaskAsync(
        CommerceAdminActor actor,
        UpsertPointTaskCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantPointClaimList> GetPointClaimsAsync(
        CommerceAdminActor actor,
        TenantPointQuery query,
        CancellationToken cancellationToken = default);

    Task<TenantPointExchangeItemList> GetPointExchangeItemsAsync(
        CommerceAdminActor actor,
        TenantPointQuery query,
        CancellationToken cancellationToken = default);

    Task<PointExchangeItem> UpsertPointExchangeItemAsync(
        CommerceAdminActor actor,
        UpsertPointExchangeItemCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantPointExchangeOrderList> GetPointExchangeOrdersAsync(
        CommerceAdminActor actor,
        TenantPointQuery query,
        CancellationToken cancellationToken = default);

    Task<PointExchangeOrder> UpdatePointExchangeOrderStatusAsync(
        CommerceAdminActor actor,
        UpdatePointExchangeOrderStatusCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantCouponList> GetCouponsAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<Coupon> UpsertCouponAsync(
        CommerceAdminActor actor,
        UpsertCouponCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantCouponRedemptionList> GetCouponRedemptionsAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<TenantCouponReport> GetCouponReportAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<TenantRefundList> GetRefundsAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<CommerceRefundRequest> CreateRefundRequestAsync(
        CommerceAdminActor actor,
        CreateRefundRequestCommand command,
        CancellationToken cancellationToken = default);

    Task<CommerceRefundRequest> UpdateRefundStatusAsync(
        CommerceAdminActor actor,
        UpdateRefundStatusCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantRefundEventList> GetRefundEventsAsync(
        CommerceAdminActor actor,
        Guid refundRequestId,
        CancellationToken cancellationToken = default);

    Task<TenantReconciliationBatchList> GetReconciliationBatchesAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<CommerceReconciliationBatch> CreateReconciliationBatchAsync(
        CommerceAdminActor actor,
        CreateReconciliationBatchCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantReconciliationIssueList> GetReconciliationIssuesAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<CommerceReconciliationIssue> UpdateReconciliationIssueAsync(
        CommerceAdminActor actor,
        UpdateReconciliationIssueCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantReconciliationItemList> GetReconciliationItemsAsync(
        CommerceAdminActor actor,
        Guid batchId,
        CancellationToken cancellationToken = default);

    Task<TenantReconciliationIssueEventList> GetReconciliationIssueEventsAsync(
        CommerceAdminActor actor,
        Guid issueId,
        CancellationToken cancellationToken = default);

    Task<TenantCommerceAnomalySummary> GetAnomalySummaryAsync(
        CommerceAdminActor actor,
        CancellationToken cancellationToken = default);

    Task<TenantAdjustmentVoucherList> GetAdjustmentVouchersAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<CommerceAdjustmentVoucher> GetAdjustmentVoucherAsync(
        CommerceAdminActor actor,
        Guid voucherId,
        CancellationToken cancellationToken = default);

    Task<CommerceAdjustmentVoucher> CreateAdjustmentVoucherAsync(
        CommerceAdminActor actor,
        CreateAdjustmentVoucherCommand command,
        CancellationToken cancellationToken = default);

    Task<CommerceAdjustmentVoucher> UpdateAdjustmentVoucherStatusAsync(
        CommerceAdminActor actor,
        UpdateAdjustmentVoucherStatusCommand command,
        CancellationToken cancellationToken = default);

    Task<TenantAdjustmentVoucherEventList> GetAdjustmentVoucherEventsAsync(
        CommerceAdminActor actor,
        Guid voucherId,
        CancellationToken cancellationToken = default);

    Task<TenantAdjustmentReport> GetAdjustmentReportAsync(
        CommerceAdminActor actor,
        CancellationToken cancellationToken = default);

    Task<ReconciliationImportPreview> PreviewReconciliationImportAsync(
        CommerceAdminActor actor,
        PreviewReconciliationImportCommand command,
        CancellationToken cancellationToken = default);

    Task<CommerceReconciliationBatch> ImportReconciliationAsync(
        CommerceAdminActor actor,
        ImportReconciliationCommand command,
        CancellationToken cancellationToken = default);

    Task<BackgroundJobItem> RequestProviderBillJobAsync(
        CommerceAdminActor actor,
        RequestProviderBillJobCommand command,
        CancellationToken cancellationToken = default);

    Task<IReadOnlyCollection<BackgroundJobItem>> GetProviderBillJobsAsync(
        CommerceAdminActor actor,
        CommerceAdminQuery query,
        CancellationToken cancellationToken = default);

    Task<CommerceRefundRequest> ProcessRefundNotificationAsync(
        Guid tenantId,
        RefundNotificationCommand command,
        CancellationToken cancellationToken = default);
}