package server

import (
	"time"

	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/agent_configuration"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/agent_configuration/rpc"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/modserver"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/pkg/agentcfg"
	"gitlab.com/gitlab-org/cluster-integration/tunnel/tool/retry"
)

const (
	getConfigurationInitBackoff   = 10 * time.Second
	getConfigurationMaxBackoff    = time.Minute
	getConfigurationResetDuration = 2 * time.Minute
	getConfigurationBackoffFactor = 2.0
	getConfigurationJitter        = 5.0
)

type Factory struct {
	AgentConfigDefaulters []func(*agentcfg.ConfigurationFile)
}

func (f *Factory) New(config *modserver.Config) (modserver.Module, error) {
	agentCfg := config.Config.Agent.Configuration
	rpc.RegisterAgentConfigurationServer(config.AgentServer, &server{
		serverAPI:                config.API,
		gitaly:                   config.Gitaly,
		gitLabClient:             config.GitLabClient,
		maxConfigurationFileSize: int64(agentCfg.MaxConfigurationFileSize),
		getConfigurationPollConfig: retry.PollConfig{
			Interval: agentCfg.PollPeriod.AsDuration(),
			Backoff: retry.NewExponentialBackoff(
				getConfigurationInitBackoff,
				getConfigurationMaxBackoff,
				getConfigurationResetDuration,
				getConfigurationBackoffFactor,
				getConfigurationJitter,
			),
		},
		gitLabExternalURL:     config.Config.Gitlab.GetExternalUrl(),
		validator:             config.Validator,
		applyDefaultsToConfig: f.applyDefaultsToConfig,
	})
	return nil, nil
}

func (f *Factory) Name() string {
	return agent_configuration.ModuleName
}

func (f *Factory) applyDefaultsToConfig(config *agentcfg.ConfigurationFile) {
	for _, cd := range f.AgentConfigDefaulters {
		cd(config)
	}
}
