package orchestrator

import (
	"time"

	chainclient "github.com/tech/sendico/chain/gateway/client"
	oracleclient "github.com/tech/sendico/fx/oracle/client"
	ledgerclient "github.com/tech/sendico/ledger/client"
	clockpkg "github.com/tech/sendico/pkg/clock"
	feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
)

// Option configures service dependencies.
type Option func(*Service)

type feesDependency struct {
	client  feesv1.FeeEngineClient
	timeout time.Duration
}

func (f feesDependency) available() bool {
	return f.client != nil
}

type ledgerDependency struct {
	client ledgerclient.Client
}

func (l ledgerDependency) available() bool {
	return l.client != nil
}

type gatewayDependency struct {
	client chainclient.Client
}

func (g gatewayDependency) available() bool {
	return g.client != nil
}

type oracleDependency struct {
	client oracleclient.Client
}

func (o oracleDependency) available() bool {
	return o.client != nil
}

// WithFeeEngine wires the fee engine client.
func WithFeeEngine(client feesv1.FeeEngineClient, timeout time.Duration) Option {
	return func(s *Service) {
		s.fees = feesDependency{
			client:  client,
			timeout: timeout,
		}
	}
}

// WithLedgerClient wires the ledger client.
func WithLedgerClient(client ledgerclient.Client) Option {
	return func(s *Service) {
		s.ledger = ledgerDependency{client: client}
	}
}

// WithChainGatewayClient wires the chain gateway client.
func WithChainGatewayClient(client chainclient.Client) Option {
	return func(s *Service) {
		s.gateway = gatewayDependency{client: client}
	}
}

// WithOracleClient wires the FX oracle client.
func WithOracleClient(client oracleclient.Client) Option {
	return func(s *Service) {
		s.oracle = oracleDependency{client: client}
	}
}

// WithClock overrides the default clock.
func WithClock(clock clockpkg.Clock) Option {
	return func(s *Service) {
		if clock != nil {
			s.clock = clock
		}
	}
}
