package storage

import (
	"context"
	"time"

	"github.com/tech/sendico/fx/storage/model"
)

type storageError string

func (e storageError) Error() string {
	return string(e)
}

var (
	ErrQuoteExpired         = storageError("fx.storage: quote expired")
	ErrQuoteConsumed        = storageError("fx.storage: quote consumed")
	ErrQuoteNotFirm         = storageError("fx.storage: quote is not firm")
	ErrQuoteConsumptionRace = storageError("fx.storage: quote consumption collision")
)

type Repository interface {
	Ping(ctx context.Context) error
	Rates() RatesStore
	Quotes() QuotesStore
	Pairs() PairStore
	Currencies() CurrencyStore
}

type RatesStore interface {
	UpsertSnapshot(ctx context.Context, snapshot *model.RateSnapshot) error
	LatestSnapshot(ctx context.Context, pair model.CurrencyPair, provider string) (*model.RateSnapshot, error)
}

type QuotesStore interface {
	Issue(ctx context.Context, quote *model.Quote) error
	GetByRef(ctx context.Context, quoteRef string) (*model.Quote, error)
	Consume(ctx context.Context, quoteRef, ledgerTxnRef string, when time.Time) (*model.Quote, error)
	ExpireIssuedBefore(ctx context.Context, cutoff time.Time) (int, error)
}

type PairStore interface {
	ListEnabled(ctx context.Context) ([]*model.Pair, error)
	Get(ctx context.Context, pair model.CurrencyPair) (*model.Pair, error)
	Upsert(ctx context.Context, p *model.Pair) error
}

type CurrencyStore interface {
	Get(ctx context.Context, code string) (*model.Currency, error)
	List(ctx context.Context, codes ...string) ([]*model.Currency, error)
	Upsert(ctx context.Context, currency *model.Currency) error
}
