package testclient

import (
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/cmd/app/config"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/cmd/app/handler"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/app"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/fakes"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/api"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/auth"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/proxy"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/sale_order"
	"github.com/AlchemyTelcoSolutions/xutils-go/xlogger"
	"github.com/pkg/errors"
)

type ServerClientBuilder struct {
	logger   xlogger.Logger
	testeApp *app.TestApp
	cfg      *config.Config
}

func NewServerClientBuilder() *ServerClientBuilder {
	return &ServerClientBuilder{}
}

func (b *ServerClientBuilder) SetLogger(logger xlogger.Logger) *ServerClientBuilder {
	b.logger = logger
	return b
}

func (b *ServerClientBuilder) SetTestApp(ta *app.TestApp) *ServerClientBuilder {
	b.testeApp = ta
	return b
}

func (b *ServerClientBuilder) SetAppConfig(cfg *config.Config) *ServerClientBuilder {
	b.cfg = cfg
	return b
}

func (b *ServerClientBuilder) checkInjectedDependencies() error {
	if b.logger == nil {
		return errors.New("logger is not set")
	}
	if b.testeApp == nil {
		return errors.New("testApp is not set")
	}

	return nil
}

func (b *ServerClientBuilder) Build() *Client {
	if err := b.checkInjectedDependencies(); err != nil {
		panic(err)
	}

	proxySvc := proxy.NewProxyService().
		SetLogger(b.logger).
		SetConfigs(b.testeApp.GetConfigs()).
		SetHttpClient(fakes.NewFakeCallistoAPIClient())
	authSvc := auth.NewAuthService().
		SetLogger(b.logger).
		SetConfigs(b.testeApp.GetConfigs()).
		SetProxyService(proxySvc)

	// Here we set the new Service with fake Clients
	SoService := sale_order.NewSaleOrderService().
		SetLogger(b.logger).
		SetConfigs(b.testeApp.GetConfigs()).
		SetProxyService(proxySvc).
		SetAuthService(authSvc).
		SetCallistoSOGRPC(fakes.NewCallistoSoFakeClient())

	server := api.NewServer(api.ServerOptions{
		Logger:       b.logger,
		SaleOrderSvc: SoService,
		ProxySvc:     proxySvc,
		Config:       b.cfg,
	})

	return NewServerClient(server)
}

type Client struct {
	client handler.ServerInterface
}

func NewServerClient(client handler.ServerInterface) *Client {
	return &Client{client: client}
}
