package seatbilling

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

func TestCreateAndSettleNewSubscriptionSeatOrder(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_new_order", now)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_new_order",
		CreatedByUserID:   "usr_org_seat_new_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "new-subscription",
		Now:               now,
	})
	require.Equal(t, OrderStatusPending, order.Order.Status)
	require.Equal(t, PaymentStatusPending, order.Payment.Status)
	require.Equal(t, int64(200000), order.Order.AmountCents)
	require.Equal(t, order.Order.AmountCents, order.Payment.AmountCents)
	require.Equal(t, CurrencyCNY, order.Order.Currency)
	require.WithinDuration(t, now.Add(SeatOrderPaymentTTL), order.Order.ExpiresAt, time.Second)

	idempotent := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_new_order",
		CreatedByUserID:   "usr_org_seat_new_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyEnterprise,
		BillingPeriod:     BillingPeriodYear,
		SeatQuantityAfter: 20,
		IdempotencyKey:    "new-subscription",
		Now:               now,
	})
	require.Equal(t, order.Order.ID, idempotent.Order.ID)
	require.Equal(t, order.Payment.ProviderOrderID, idempotent.Payment.ProviderOrderID)

	paidAt := now.Add(2 * time.Minute)
	settled := settleSeatOrderForTest(t, ctx, store, order, paidAt)
	require.Equal(t, OrderStatusPaid, settled.Order.Status)
	require.Equal(t, PaymentStatusPaid, settled.Payment.Status)
	require.NotNil(t, settled.Order.SettledAt)
	require.NotNil(t, settled.Order.AppliedAt)

	subscription, found, err := store.LoadSubscription(ctx, "org_seat_new_order")
	require.NoError(t, err)
	require.True(t, found)
	require.Equal(t, SubscriptionStatusActive, subscription.Status)
	require.Equal(t, PlanKeyTeam, subscription.PlanKey)
	require.Equal(t, BillingPeriodMonth, subscription.BillingPeriod)
	require.Equal(t, 4, subscription.SeatQuantity)
	require.EqualValues(t, 10, subscription.ManagedAgentsPerSeatSnapshot)
	require.Equal(t, 50, subscription.MaxHumanSeatsSnapshot)
	require.EqualValues(t, 50000, subscription.UnitPriceCentsSnapshot)
	require.WithinDuration(t, paidAt, subscription.CurrentPeriodStart, time.Second)
	require.WithinDuration(t, paidAt.AddDate(0, 1, 0), subscription.CurrentPeriodEnd, time.Second)

	replayed := settleSeatOrderForTest(t, ctx, store, order, paidAt.Add(time.Minute))
	require.Equal(t, settled.Order.ID, replayed.Order.ID)
	require.Equal(t, OrderStatusPaid, replayed.Order.Status)
	subscriptionAfterReplay, found, err := store.LoadSubscription(ctx, "org_seat_new_order")
	require.NoError(t, err)
	require.True(t, found)
	require.WithinDuration(t, subscription.CurrentPeriodEnd, subscriptionAfterReplay.CurrentPeriodEnd, time.Second)
}

func TestCreateSeatOrderRejectsSecondPendingUntilExpired(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_pending_order", now)

	first := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_pending_order",
		CreatedByUserID:   "usr_org_seat_pending_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 3,
		IdempotencyKey:    "first",
		Now:               now,
	})

	_, err := store.CreateSeatOrder(ctx, CreateSeatOrderParams{
		OrganizationID:    "org_seat_pending_order",
		CreatedByUserID:   "usr_org_seat_pending_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyEnterprise,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "second",
		Now:               now.Add(time.Minute),
	})
	require.Error(t, err)
	require.True(t, errors.Is(err, storeerr.ErrConflict))

	second := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_pending_order",
		CreatedByUserID:   "usr_org_seat_pending_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyEnterprise,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "second",
		Now:               first.Order.ExpiresAt.Add(time.Second),
	})
	require.NotEqual(t, first.Order.ID, second.Order.ID)

	expiredFirst, found, err := store.LoadSeatOrder(ctx, "org_seat_pending_order", first.Order.ID)
	require.NoError(t, err)
	require.True(t, found)
	require.Equal(t, OrderStatusExpired, expiredFirst.Order.Status)
	require.Equal(t, OrderStatusPending, second.Order.Status)
}

func TestAddSeatsOrderUsesSubscriptionSnapshotProration(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	periodStart := time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC)
	periodEnd := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_add_order", now)
	seedSeatSubscription(t, ctx, db, "org_seat_add_order", SubscriptionStatusActive, PlanKeyTeam, BillingPeriodMonth, 4, 10, 10, 3900, periodStart, periodEnd, now)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_add_order",
		CreatedByUserID:   "usr_org_seat_add_order",
		OrderType:         OrderTypeAddSeats,
		SeatQuantityAfter: 6,
		IdempotencyKey:    "add-seats",
		Now:               now,
	})
	require.Equal(t, OrderTypeAddSeats, order.Order.OrderType)
	require.Equal(t, 4, order.Order.SeatQuantityBefore)
	require.Equal(t, 6, order.Order.SeatQuantityAfter)
	require.Equal(t, 2, order.Order.SeatDelta)
	require.EqualValues(t, 7800, order.Order.BaseAmountCents)
	require.EqualValues(t, 5980, order.Order.AmountCents)
	require.Contains(t, order.Order.ProrationSnapshotJSON, `"remaining_days":23`)
	require.Contains(t, order.Order.ProrationSnapshotJSON, `"period_days":30`)

	settled := settleSeatOrderForTest(t, ctx, store, order, now.Add(time.Minute))
	require.Equal(t, OrderStatusPaid, settled.Order.Status)
	subscription, found, err := store.LoadSubscription(ctx, "org_seat_add_order")
	require.NoError(t, err)
	require.True(t, found)
	require.Equal(t, 6, subscription.SeatQuantity)
	require.Equal(t, PlanKeyTeam, subscription.PlanKey)
	require.WithinDuration(t, periodEnd, subscription.CurrentPeriodEnd, time.Second)
	require.EqualValues(t, 3900, subscription.UnitPriceCentsSnapshot)
}

func TestUpgradeTierOrderUsesTargetPlanProration(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	periodStart := time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC)
	periodEnd := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_upgrade_order", now)
	seedSeatSubscription(t, ctx, db, "org_seat_upgrade_order", SubscriptionStatusActive, PlanKeyTeam, BillingPeriodMonth, 4, 10, 10, 3900, periodStart, periodEnd, now)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:  "org_seat_upgrade_order",
		CreatedByUserID: "usr_org_seat_upgrade_order",
		OrderType:       OrderTypeUpgradeTier,
		ToPlanKey:       PlanKeyEnterprise,
		IdempotencyKey:  "upgrade-tier",
		Now:             now,
	})
	require.Equal(t, OrderTypeUpgradeTier, order.Order.OrderType)
	require.EqualValues(t, 384400, order.Order.BaseAmountCents)
	require.EqualValues(t, 294707, order.Order.AmountCents)
	require.EqualValues(t, 3900, order.Order.UnitPriceCentsSnapshot)
	require.EqualValues(t, 100000, order.Order.TargetUnitPriceCentsSnapshot)

	settleSeatOrderForTest(t, ctx, store, order, now.Add(time.Minute))
	subscription, found, err := store.LoadSubscription(ctx, "org_seat_upgrade_order")
	require.NoError(t, err)
	require.True(t, found)
	require.Equal(t, PlanKeyEnterprise, subscription.PlanKey)
	require.Equal(t, 4, subscription.SeatQuantity)
	require.EqualValues(t, 20, subscription.ManagedAgentsPerSeatSnapshot)
	require.Equal(t, 0, subscription.MaxHumanSeatsSnapshot)
	require.EqualValues(t, 100000, subscription.UnitPriceCentsSnapshot)
	require.WithinDuration(t, periodEnd, subscription.CurrentPeriodEnd, time.Second)
}

func TestRenewSubscriptionOrderExtendsActiveOrRestartsExpiredPeriod(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)

	seedSeatBillingOrganization(t, ctx, db, "org_seat_active_renew", now)
	activeStart := time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC)
	activeEnd := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)
	seedSeatSubscription(t, ctx, db, "org_seat_active_renew", SubscriptionStatusActive, PlanKeyTeam, BillingPeriodMonth, 4, 10, 10, 3900, activeStart, activeEnd, now)
	activeOrder := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:  "org_seat_active_renew",
		CreatedByUserID: "usr_org_seat_active_renew",
		OrderType:       OrderTypeRenewSubscription,
		IdempotencyKey:  "active-renew",
		Now:             now,
	})
	require.EqualValues(t, 200000, activeOrder.Order.AmountCents)
	settleSeatOrderForTest(t, ctx, store, activeOrder, now.Add(time.Minute))
	activeSubscription, found, err := store.LoadSubscription(ctx, "org_seat_active_renew")
	require.NoError(t, err)
	require.True(t, found)
	require.WithinDuration(t, activeStart, activeSubscription.CurrentPeriodStart, time.Second)
	require.WithinDuration(t, activeEnd.AddDate(0, 1, 0), activeSubscription.CurrentPeriodEnd, time.Second)

	seedSeatBillingOrganization(t, ctx, db, "org_seat_expired_renew", now)
	expiredStart := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC)
	expiredEnd := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC)
	seedSeatSubscription(t, ctx, db, "org_seat_expired_renew", SubscriptionStatusExpired, PlanKeyEnterprise, BillingPeriodMonth, 5, 20, 20, 9900, expiredStart, expiredEnd, now)
	expiredOrder := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:  "org_seat_expired_renew",
		CreatedByUserID: "usr_org_seat_expired_renew",
		OrderType:       OrderTypeRenewSubscription,
		IdempotencyKey:  "expired-renew",
		Now:             now,
	})
	require.EqualValues(t, 500000, expiredOrder.Order.AmountCents)
	paidAt := now.Add(time.Minute)
	settleSeatOrderForTest(t, ctx, store, expiredOrder, paidAt)
	expiredSubscription, found, err := store.LoadSubscription(ctx, "org_seat_expired_renew")
	require.NoError(t, err)
	require.True(t, found)
	require.WithinDuration(t, paidAt, expiredSubscription.CurrentPeriodStart, time.Second)
	require.WithinDuration(t, paidAt.AddDate(0, 1, 0), expiredSubscription.CurrentPeriodEnd, time.Second)
}

func TestLatePaidSeatOrderAppliesWhenNoNewerSeatOrder(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_late_order", now)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_late_order",
		CreatedByUserID:   "usr_org_seat_late_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "late",
		Now:               now,
	})
	latePaidAt := order.Order.ExpiresAt.Add(time.Second)
	settled := settleSeatOrderForTest(t, ctx, store, order, latePaidAt)
	require.Equal(t, OrderStatusPaid, settled.Order.Status)
	require.Equal(t, PaymentStatusPaid, settled.Payment.Status)
	require.NotNil(t, settled.Order.AppliedAt)
	subscription, found, err := store.LoadSubscription(ctx, "org_seat_late_order")
	require.NoError(t, err)
	require.True(t, found)
	require.Equal(t, PlanKeyTeam, subscription.PlanKey)
	require.Equal(t, 4, subscription.SeatQuantity)
	require.WithinDuration(t, latePaidAt, subscription.CurrentPeriodStart, time.Second)
	require.WithinDuration(t, latePaidAt.AddDate(0, 1, 0), subscription.CurrentPeriodEnd, time.Second)
}

func TestPaidUnappliedSeatOrderAppliesOnRetryWhenNoNewerSeatOrder(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_unapplied_retry", now)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_unapplied_retry",
		CreatedByUserID:   "usr_org_seat_unapplied_retry",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "unapplied-retry",
		Now:               now,
	})
	paidAt := order.Order.ExpiresAt.Add(time.Second)
	_, err := db.Exec(ctx, `
UPDATE organization_seat_orders
SET status = $1,
    pending_order_key = NULL,
    settled_at = $2,
    applied_at = NULL,
    updated_at = $3
WHERE id = $4
`, OrderStatusPaidUnapplied, paidAt, paidAt, order.Order.ID)
	require.NoError(t, err)
	_, err = db.Exec(ctx, `
UPDATE organization_seat_payment_orders
SET status = $1,
    paid_at = $2,
    updated_at = $3
WHERE seat_order_id = $4
`, PaymentStatusPaid, paidAt, paidAt, order.Order.ID)
	require.NoError(t, err)

	settled := settleSeatOrderForTest(t, ctx, store, order, paidAt.Add(time.Minute))
	require.Equal(t, OrderStatusPaid, settled.Order.Status)
	require.Equal(t, PaymentStatusPaid, settled.Payment.Status)
	require.NotNil(t, settled.Order.AppliedAt)
	subscription, found, err := store.LoadSubscription(ctx, "org_seat_unapplied_retry")
	require.NoError(t, err)
	require.True(t, found)
	require.Equal(t, PlanKeyTeam, subscription.PlanKey)
	require.Equal(t, 4, subscription.SeatQuantity)
	require.WithinDuration(t, paidAt, subscription.CurrentPeriodStart, time.Second)
}

func TestCancelPendingSeatOrderClosesPayment(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_cancel_order", now)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_cancel_order",
		CreatedByUserID:   "usr_org_seat_cancel_order",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "cancel",
		Now:               now,
	})
	cancelled := cancelSeatOrderForTest(t, ctx, store, CancelSeatOrderParams{
		OrganizationID:    "org_seat_cancel_order",
		OrderID:           order.Order.ID,
		CancelledByUserID: "usr_org_seat_cancel_order",
		Now:               now.Add(time.Minute),
		RawPayloadJSON:    `{"provider_result":"closed"}`,
	})
	require.Equal(t, OrderStatusCancelled, cancelled.Order.Status)
	require.Equal(t, PaymentStatusClosed, cancelled.Payment.Status)
	require.NotNil(t, cancelled.Order.CancelledByUserID)
	require.Equal(t, "usr_org_seat_cancel_order", *cancelled.Order.CancelledByUserID)
	require.NotNil(t, cancelled.Payment.ClosedAt)

	_, err := store.CancelSeatOrder(ctx, CancelSeatOrderParams{
		OrganizationID:    "org_seat_cancel_order",
		OrderID:           order.Order.ID,
		CancelledByUserID: "usr_org_seat_cancel_order",
		Now:               now.Add(2 * time.Minute),
		RawPayloadJSON:    `{}`,
	})
	require.Error(t, err)
	require.True(t, errors.Is(err, storeerr.ErrConflict))
}

func TestListSeatPaymentHistoryIsMonthBounded(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	now := time.Date(2026, 6, 8, 10, 0, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_history", now)

	juneOrder := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_history",
		CreatedByUserID:   "usr_org_seat_history",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "june",
		Now:               now,
	})
	settleSeatOrderForTest(t, ctx, store, juneOrder, now.Add(time.Minute))

	history, err := store.ListSeatPaymentHistory(ctx, ListSeatPaymentHistoryParams{
		OrganizationID: "org_seat_history",
		MonthStart:     time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC),
		MonthEnd:       time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC),
		Limit:          10,
	})
	require.NoError(t, err)
	require.Len(t, history, 1)
	require.Equal(t, juneOrder.Order.ID, history[0].Order.ID)
	require.Equal(t, juneOrder.Payment.ProviderOrderID, history[0].Payment.ProviderOrderID)

	mayHistory, err := store.ListSeatPaymentHistory(ctx, ListSeatPaymentHistoryParams{
		OrganizationID: "org_seat_history",
		MonthStart:     time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC),
		MonthEnd:       time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC),
		Limit:          10,
	})
	require.NoError(t, err)
	require.Empty(t, mayHistory)
}

func TestListSeatPaymentHistoryUsesPaidAtForPaidOrders(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	db := startSeatBillingRollbackDB(t, ctx)
	store := New(db)
	createdAt := time.Date(2026, 5, 31, 23, 55, 0, 0, time.UTC)
	paidAt := time.Date(2026, 6, 1, 0, 5, 0, 0, time.UTC)
	seedSeatBillingOrganization(t, ctx, db, "org_seat_history_paid_at", createdAt)

	order := createSeatOrderForTest(t, ctx, store, CreateSeatOrderParams{
		OrganizationID:    "org_seat_history_paid_at",
		CreatedByUserID:   "usr_org_seat_history_paid_at",
		OrderType:         OrderTypeNewSubscription,
		ToPlanKey:         PlanKeyTeam,
		BillingPeriod:     BillingPeriodMonth,
		SeatQuantityAfter: 4,
		IdempotencyKey:    "cross-month",
		Now:               createdAt,
	})
	settled := settleSeatOrderForTest(t, ctx, store, order, paidAt)

	juneHistory, err := store.ListSeatPaymentHistory(ctx, ListSeatPaymentHistoryParams{
		OrganizationID: "org_seat_history_paid_at",
		MonthStart:     time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC),
		MonthEnd:       time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC),
		Limit:          10,
	})
	require.NoError(t, err)
	require.Len(t, juneHistory, 1)
	require.Equal(t, settled.Order.ID, juneHistory[0].Order.ID)
	require.NotNil(t, juneHistory[0].Payment.PaidAt)
	require.WithinDuration(t, paidAt, *juneHistory[0].Payment.PaidAt, time.Second)

	mayHistory, err := store.ListSeatPaymentHistory(ctx, ListSeatPaymentHistoryParams{
		OrganizationID: "org_seat_history_paid_at",
		MonthStart:     time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC),
		MonthEnd:       time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC),
		Limit:          10,
	})
	require.NoError(t, err)
	require.Empty(t, mayHistory)
}

func createSeatOrderForTest(t *testing.T, ctx context.Context, store *Store, params CreateSeatOrderParams) SeatOrderWithPayment {
	t.Helper()
	order, err := store.CreateSeatOrder(ctx, params)
	require.NoError(t, err)
	return order
}

func settleSeatOrderForTest(t *testing.T, ctx context.Context, store *Store, order SeatOrderWithPayment, paidAt time.Time) SeatOrderWithPayment {
	t.Helper()
	paidAt = paidAt.UTC()
	settled, err := store.SettleSeatPaymentPaid(ctx, SettleSeatPaymentParams{
		Provider:        PaymentProviderAlipay,
		ProviderOrderID: order.Payment.ProviderOrderID,
		AmountCents:     order.Order.AmountCents,
		Currency:        order.Order.Currency,
		PaidAt:          &paidAt,
		ConfirmedAt:     paidAt.Add(time.Second),
		RawPayloadJSON:  `{"trade_status":"TRADE_SUCCESS"}`,
	})
	require.NoError(t, err)
	return settled
}

func cancelSeatOrderForTest(t *testing.T, ctx context.Context, store *Store, params CancelSeatOrderParams) SeatOrderWithPayment {
	t.Helper()
	order, err := store.CancelSeatOrder(ctx, params)
	require.NoError(t, err)
	return order
}
