package modules

import (
	vulnhandler "security-center-backend/internal/modules/vuln/handler"
	vulnrepository "security-center-backend/internal/modules/vuln/repository"
	vulnservice "security-center-backend/internal/modules/vuln/service"
	"security-center-backend/internal/pkg/cache"
	"security-center-backend/internal/pkg/storage"
	"security-center-backend/internal/repository"
	"security-center-backend/internal/service/directory"
)

type VulnModule struct {
	Module *vulnhandler.Module
}

type VulnBuildInput struct {
	VulnRepo              vulnrepository.VulnerabilityRepository
	VulnEventRepo         vulnrepository.VulnerabilityEventRepository
	VulnCommentRepo       vulnrepository.VulnerabilityCommentRepository
	VulnAttachmentRepo    vulnrepository.VulnerabilityAttachmentRepository
	VulnSLARepo           vulnrepository.SLARuleRepository
	VulnRequiredFieldRepo vulnrepository.SubmissionRequiredFieldRepository
	VulnTypeRepo          vulnrepository.VulnerabilityTypeRepository
	VulnSourceRepo        vulnrepository.SourceRepository
	TagRepo               vulnrepository.TagRepository
	ChannelRepo           vulnrepository.DiscoveryChannelRepository
	UserRepo              repository.UserRepository
	EmployeeDir           directory.EmployeeDirectory
	PickerReadsBlocked    func() bool
	FileUploader          storage.FileUploader
	Cache                 *cache.Cache
}

func BuildVuln(input VulnBuildInput) *VulnModule {
	var (
		mainHandler      *vulnhandler.Handler
		tagHandler       *vulnhandler.TagHandler
		typeHandler      *vulnhandler.VulnerabilityTypeHandler
		sourceHandler    *vulnhandler.SourceHandler
		discoveryHandler *vulnhandler.DiscoveryChannelHandler
	)

	if input.VulnRepo != nil {
		vulnSvc := vulnservice.New(
			input.VulnRepo,
			input.ChannelRepo,
			input.VulnTypeRepo,
			input.VulnSourceRepo,
			input.VulnEventRepo,
			input.VulnCommentRepo,
			input.VulnAttachmentRepo,
			input.VulnSLARepo,
			input.VulnRequiredFieldRepo,
			input.UserRepo,
			input.EmployeeDir,
		)
		vulnSvc.SetPickerReadsBlocked(input.PickerReadsBlocked)
		mainHandler = vulnhandler.New(vulnSvc, input.FileUploader, input.Cache)
	}

	if input.TagRepo != nil {
		tagSvc := vulnservice.NewTagService(input.TagRepo)
		tagHandler = vulnhandler.NewTagHandler(tagSvc)
	}
	if input.VulnTypeRepo != nil {
		typeSvc := vulnservice.NewVulnerabilityTypeService(input.VulnTypeRepo)
		typeHandler = vulnhandler.NewVulnerabilityTypeHandler(typeSvc)
	}
	if input.VulnSourceRepo != nil {
		sourceSvc := vulnservice.NewSourceService(input.VulnSourceRepo)
		sourceHandler = vulnhandler.NewSourceHandler(sourceSvc)
	}
	if input.ChannelRepo != nil {
		channelSvc := vulnservice.NewDiscoveryChannelService(input.ChannelRepo)
		discoveryHandler = vulnhandler.NewDiscoveryChannelHandler(channelSvc)
	}

	return &VulnModule{
		Module: vulnhandler.NewModule(mainHandler, tagHandler, typeHandler, sourceHandler, discoveryHandler),
	}
}
