package rail

import (
	"context"

	paymenttypes "github.com/tech/sendico/pkg/payments/types"
)

// Money represents a currency amount using decimal-safe strings.
type Money = paymenttypes.Money

const (
	TransferStatusUnspecified = "UNSPECIFIED"
	TransferStatusSuccess     = "SUCCESS"
	TransferStatusFailed      = "FAILED"
	TransferStatusRejected    = "REJECTED"
	TransferStatusPending     = "PENDING"
)

// RailCapabilities are declared per gateway instance.
type RailCapabilities struct {
	CanPayIn               bool
	CanPayOut              bool
	CanReadBalance         bool
	CanSendFee             bool
	RequiresObserveConfirm bool
	CanBlock               bool
	CanRelease             bool
}

// FeeBreakdown provides a gateway-level fee description.
type FeeBreakdown struct {
	FeeCode     string
	Amount      *Money
	Description string
}

// TransferRequest defines the inputs for sending value through a rail gateway.
type TransferRequest struct {
	OrganizationRef string
	FromAccountID   string
	ToAccountID     string
	Currency        string
	Network         string
	Amount          string
	Fee             *Money
	Fees            []FeeBreakdown
	IdempotencyKey  string
	Metadata        map[string]string
	ClientReference string
	DestinationMemo string
}

// BlockRequest defines the inputs for reserving value through a rail gateway.
type BlockRequest struct {
	OrganizationRef string
	AccountID       string
	Currency        string
	Amount          string
	IdempotencyKey  string
	Metadata        map[string]string
	ClientReference string
}

// ReleaseRequest defines the inputs for releasing a prior block.
type ReleaseRequest struct {
	ReferenceID     string
	IdempotencyKey  string
	Metadata        map[string]string
	ClientReference string
}

// RailResult reports the outcome of a rail gateway operation.
type RailResult struct {
	ReferenceID string
	Status      string
	FinalAmount *Money
	Error       *RailError
}

// ObserveResult reports the outcome of a confirmation observation.
type ObserveResult struct {
	ReferenceID string
	Status      string
	FinalAmount *Money
	Error       *RailError
}

// RailError captures structured failure details from a gateway.
type RailError struct {
	Code           string
	Message        string
	CanRetry       bool
	ShouldRollback bool
}

// RailGateway exposes unified gateway operations for external rails.
type RailGateway interface {
	Rail() string
	Network() string
	Capabilities() RailCapabilities
	Send(ctx context.Context, req TransferRequest) (RailResult, error)
	Observe(ctx context.Context, referenceID string) (ObserveResult, error)
	Block(ctx context.Context, req BlockRequest) (RailResult, error)
	Release(ctx context.Context, req ReleaseRequest) (RailResult, error)
}
