package app

import (
	"context"
	controller "gitlab.com/gitlab-org/spamcheck/app/controllers"
	"gitlab.com/gitlab-org/spamcheck/app/protocol/grpc"
	"gitlab.com/gitlab-org/spamcheck/app/protocol/rest"
	services "gitlab.com/gitlab-org/spamcheck/app/services"
	"gitlab.com/gitlab-org/spamcheck/app/validations"
	config "gitlab.com/gitlab-org/spamcheck/app/config"
	logging "gitlab.com/gitlab-org/spamcheck/app/logging"
	monitoring "gitlab.com/gitlab-org/spamcheck/app/monitoring"
	tracing "gitlab.com/gitlab-org/spamcheck/app/tracing"
	"gitlab.com/gitlab-org/labkit/log"
)

// SpamCheck is the main application entrypoint
type SpamCheck struct {
}

// Run runs gRPC server and HTTP gateway
func (s *SpamCheck) Run() error {
	ctx := context.Background()

	cfg, err := config.RunConfig()
	if err != nil {
		log.WithError(err).Error("Run(): Error loading configuration")
		return err
	}

	// Initialize LabKit services
	setupLabKit(cfg)

	// Set up controller, service, and validations
	controller := controller.CreateSpamCheckController(cfg)
	validations := validations.CreateSpamCheckValidations()

	v1API := services.CreateSpamCheckService(controller, validations)

	// run HTTP gateway
	go func() {
		_ = rest.RunServer(ctx, cfg.GRPC.Port, cfg.REST.ExternalPort)
	}()

	return grpc.RunServer(ctx, v1API, cfg.GRPC.Port)
}

// Load LabKit configurations/setup
func setupLabKit (cfg *config.Config) {
	err := logging.LoadLogging(cfg)
	if err != nil {
		log.WithError(err).Panic("Error loading logging")
	}

	err = monitoring.LoadMonitoring(cfg)
	if err != nil {
		log.WithError(err).Panic("Monitoring stopped")
	}

	tracing.LoadTracing()
}