package rail

import (
	"context"

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

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

type TransferStatus string

const (
	TransferStatusUnspecified TransferStatus = "unspecified"
	TransferStatusCreated     TransferStatus = "created"
	TransferStatusSuccess     TransferStatus = "success"
	TransferStatusFailed      TransferStatus = "failed"
	TransferStatusWaiting     TransferStatus = "waiting"
	TransferStatusProcessing  TransferStatus = "processing"
	TransferStatusCancelled   TransferStatus = "cancelled"
)

// OperationResult represents the outcome status of an operation in a gateway
type OperationResult string

const (
	OperationResultSuccess   OperationResult = "success"
	OperationResultFailed    OperationResult = "failed"
	OperationResultCancelled OperationResult = "cancelled"
)

// 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
	IntentRef       string
	OperationRef    string
	PaymentRef      string
	FromAccountID   string
	ToAccountID     string
	Currency        string
	Network         string
	Amount          string
	Fee             *Money
	Fees            []FeeBreakdown
	IdempotencyKey  string
	Metadata        map[string]string
	DestinationMemo string
	FromRole        account_role.AccountRole
	ToRole          account_role.AccountRole
}

// 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
	PaymentRef      string
}

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

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

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

// Error captures structured failure details from a gateway.
type Error 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)
}
