// Package approval 定义业务用例依赖的渠道无关审批接缝。
package approval

import (
	"context"
	"time"

	"gorm.io/gorm"
)

// PrepareRequest 是业务写入前执行审批渠道可用性检查的请求。
type PrepareRequest struct {
	BusinessType       string
	SubmitterAccountID uint
	CorrelationID      string
}

// Preparation 是渠道可用性检查返回的短期、不透明准备凭据。
type Preparation struct {
	provider           string
	businessType       string
	submitterAccountID uint
	correlationID      string
	expiresAt          time.Time
	issuer             *CreationService
	providerContext    ProviderPreparation
}

// CreateRequest 是业务事务内创建通用审批实例的请求。
type CreateRequest struct {
	Preparation        Preparation
	BusinessType       string
	BusinessID         uint
	SubmitterAccountID uint
	SubmitterSnapshot  []byte
	RequestSnapshot    []byte
	CorrelationID      string
}

// Reference 是业务表保存的通用审批实例引用。
type Reference struct {
	InstanceID uint
	Status     int
}

// Port 是退款、线下充值等业务用例唯一依赖的审批创建接缝。
// Prepare 必须在业务事务前确认 Adapter、场景和发起身份可用；CreateInTx 必须复核准备凭据并使用调用方事务写入审批事实。
type Port interface {
	Prepare(ctx context.Context, request PrepareRequest) (Preparation, error)
	CreateInTx(ctx context.Context, tx *gorm.DB, request CreateRequest) (Reference, error)
}

// ProviderPreparation 是渠道 Adapter 在事务前完成场景和发起身份检查后返回的内部准备结果。
// ChannelContext 只能包含后续写入渠道专属表所需的安全快照，不得包含密钥或访问令牌。
type ProviderPreparation struct {
	Provider       string
	ChannelContext []byte
}

// ProviderPort 定义具体审批渠道对通用创建用例提供的防腐接缝。
type ProviderPort interface {
	Prepare(ctx context.Context, request PrepareRequest) (ProviderPreparation, error)
	CreateContextInTx(ctx context.Context, tx *gorm.DB, preparation ProviderPreparation, instanceID uint) error
}

// SubmissionRequestedEvent 是渠道提交 Worker 接收的通用申请事件。
type SubmissionRequestedEvent struct {
	EventID            string    `json:"event_id"`
	InstanceID         uint      `json:"instance_id"`
	BusinessType       string    `json:"business_type"`
	BusinessID         uint      `json:"business_id"`
	SubmitterAccountID uint      `json:"submitter_account_id"`
	Provider           string    `json:"provider"`
	CorrelationID      string    `json:"correlation_id"`
	OccurredAt         time.Time `json:"occurred_at"`
}

// SubmissionEventWriter 在调用方业务事务中追加渠道提交 Outbox。
type SubmissionEventWriter interface {
	Append(ctx context.Context, tx *gorm.DB, event SubmissionRequestedEvent) error
}
