package agentw

import (
	"errors"
	"fmt"

	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/agentwcfg"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/modagentw"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/observability/agent"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/prototool"
)

type Factory struct {
	agent.Factory
	DefaultGRPCLogLevel agentwcfg.LogLevelEnum
}

func (f *Factory) New(config *modagentw.Config) (modagentw.Module, error) {
	listener, err := f.GetListenerFn()
	if err != nil {
		return nil, err
	}

	return &agent.Module[*agentwcfg.AgentConfiguration]{
		Log:          config.Log,
		LogLevel:     f.LogLevel,
		GRPCLogLevel: f.GRPCLogLevel,
		API:          config.API,
		Gatherer:     f.Gatherer,
		Registerer:   f.Registerer,
		Listener:     listener,
		ServerName:   config.AgentNameVersion,
		CfgAccessor: func(cfg *agentwcfg.AgentConfiguration) *agent.ModuleCfg {
			return &agent.ModuleCfg{
				LogLevel:     cfg.Observability.Logging.Level.String(),
				GRPCLogLevel: cfg.Observability.Logging.GrpcLevel.String(),
			}
		},
		DefaultAndValidateConfigurationCallback: func(cfg *agentwcfg.AgentConfiguration) error {
			prototool.NotNil(&cfg.Observability)
			prototool.NotNil(&cfg.Observability.Logging)
			if cfg.Observability.Logging.GrpcLevel == nil {
				cfg.Observability.Logging.GrpcLevel = &f.DefaultGRPCLogLevel
			}
			err := errors.Join(
				agent.ValidateLogLevel(cfg.Observability.Logging.Level.String()),
				agent.ValidateLogLevel(cfg.Observability.Logging.GrpcLevel.String()),
			)
			if err != nil {
				return fmt.Errorf("logging: %w", err)
			}
			return nil
		},
	}, nil
}
