package serverimp

import (
	oracleclient "github.com/tech/sendico/fx/oracle/client"
	mntxclient "github.com/tech/sendico/gateway/mntx/client"
	ledgerclient "github.com/tech/sendico/ledger/client"
	"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrator"
	feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
)

type orchestratorDeps struct {
	feesClient            feesv1.FeeEngineClient
	ledgerClient          ledgerclient.Client
	mntxClient            mntxclient.Client
	oracleClient          oracleclient.Client
	gatewayInvokeResolver orchestrator.GatewayInvokeResolver
}

func (i *Imp) initDependencies(_ *config) *orchestratorDeps {
	deps := &orchestratorDeps{}
	if i.discoveryReg == nil {
		if i.logger != nil {
			i.logger.Warn("Discovery registry unavailable; downstream clients disabled")
		}
		return deps
	}

	i.discoveryClients = newDiscoveryClientResolver(i.logger, i.discoveryReg)
	deps.feesClient = &discoveryFeeClient{resolver: i.discoveryClients}
	deps.ledgerClient = &discoveryLedgerClient{resolver: i.discoveryClients}
	deps.oracleClient = &discoveryOracleClient{resolver: i.discoveryClients}
	deps.mntxClient = &discoveryMntxClient{resolver: i.discoveryClients}
	deps.gatewayInvokeResolver = discoveryGatewayInvokeResolver{resolver: i.discoveryClients}
	return deps
}

func (i *Imp) buildServiceOptions(cfg *config, deps *orchestratorDeps) []orchestrator.Option {
	if cfg == nil || deps == nil {
		return nil
	}
	opts := []orchestrator.Option{}
	if deps.feesClient != nil {
		opts = append(opts, orchestrator.WithFeeEngine(deps.feesClient, cfg.Fees.callTimeout()))
	}
	if deps.ledgerClient != nil {
		opts = append(opts, orchestrator.WithLedgerClient(deps.ledgerClient))
	}
	if deps.mntxClient != nil {
		opts = append(opts, orchestrator.WithMntxGateway(deps.mntxClient))
	}
	if deps.oracleClient != nil {
		opts = append(opts, orchestrator.WithOracleClient(deps.oracleClient))
	}
	if deps.gatewayInvokeResolver != nil {
		opts = append(opts, orchestrator.WithGatewayInvokeResolver(deps.gatewayInvokeResolver))
	}
	if routes := buildCardGatewayRoutes(cfg.CardGateways); len(routes) > 0 {
		opts = append(opts, orchestrator.WithCardGatewayRoutes(routes))
	}
	if feeAccounts := buildFeeLedgerAccounts(cfg.FeeAccounts); len(feeAccounts) > 0 {
		opts = append(opts, orchestrator.WithFeeLedgerAccounts(feeAccounts))
	}
	if registry := buildGatewayRegistry(i.logger, cfg.GatewayInstances, i.discoveryReg); registry != nil {
		opts = append(opts, orchestrator.WithGatewayRegistry(registry))
	}
	return opts
}
