package container import ( "context" "os" "autostore/internal/application/commands" "autostore/internal/application/interfaces" "autostore/internal/application/queries" "autostore/internal/config" "autostore/internal/domain/specifications" "autostore/internal/infrastructure/auth" "autostore/internal/infrastructure/http" "autostore/internal/infrastructure/logging" "autostore/internal/infrastructure/repositories" "autostore/internal/infrastructure/scheduler" "autostore/internal/infrastructure/services" "autostore/internal/infrastructure/time" "autostore/internal/presentation/controllers" "autostore/internal/presentation/middleware" "autostore/internal/presentation/server" ) type Container struct { config *config.Config // Infrastructure logger interfaces.ILogger timeProvider interfaces.ITimeProvider authService interfaces.IAuthService expiredItemsScheduler *scheduler.ExpiredItemsScheduler // Domain expirationSpec *specifications.ItemExpirationSpec // Application addItemCommand *commands.AddItemCommand deleteItemCommand *commands.DeleteItemCommand handleExpiredItemsCommand *commands.HandleExpiredItemsCommand loginUserCommand *commands.LoginUserCommand getItemQuery *queries.GetItemQuery listItemsQuery *queries.ListItemsQuery // Presentation itemsController *controllers.ItemsController authController *controllers.AuthController jwtMiddleware *middleware.JWTMiddleware server *server.Server } func NewContainer(config *config.Config) *Container { return &Container{ config: config, } } func (c *Container) Initialize() error { // Initialize infrastructure c.logger = logging.NewStandardLogger(os.Stdout) c.timeProvider = time.NewSystemTimeProvider() // Initialize user repository userRepository := repositories.NewFileUserRepository(c.config.DataDirectory, c.logger) // Initialize user initialization service and create default users userInitService := services.NewUserInitializationService(userRepository, c.logger) if err := userInitService.InitializeDefaultUsers(); err != nil { c.logger.Error(context.Background(), "Failed to initialize default users", "error", err) // Continue even if user initialization fails } // Initialize auth service with user repository c.authService = auth.NewJWTAuthService(userRepository, c.config.JWTSecret, c.logger) // Initialize domain c.expirationSpec = specifications.NewItemExpirationSpec() // Initialize item repository itemRepository := repositories.NewFileItemRepository(c.config.DataDirectory, c.logger) // Initialize order service orderService := http.NewOrderURLHttpClient(c.logger) // Initialize application c.addItemCommand = commands.NewAddItemCommand(itemRepository, orderService, c.timeProvider, c.expirationSpec, c.logger) c.deleteItemCommand = commands.NewDeleteItemCommand(itemRepository, c.logger) c.handleExpiredItemsCommand = commands.NewHandleExpiredItemsCommand(itemRepository, orderService, c.timeProvider, c.expirationSpec, c.logger) c.loginUserCommand = commands.NewLoginUserCommand(c.authService, c.logger) c.getItemQuery = queries.NewGetItemQuery(itemRepository, c.logger) c.listItemsQuery = queries.NewListItemsQuery(itemRepository, c.logger) // Initialize scheduler c.expiredItemsScheduler = scheduler.NewExpiredItemsScheduler(c.handleExpiredItemsCommand, c.logger) // Initialize presentation c.itemsController = controllers.NewItemsController(c.addItemCommand, c.getItemQuery, c.listItemsQuery, c.deleteItemCommand, c.logger) c.authController = controllers.NewAuthController(c.loginUserCommand, c.logger) c.jwtMiddleware = middleware.NewJWTMiddleware(c.authService, c.logger) serverConfig := &server.Config{ Port: c.config.ServerPort, ReadTimeout: c.config.ReadTimeout, WriteTimeout: c.config.WriteTimeout, ShutdownTimeout: c.config.ShutdownTimeout, } c.server = server.NewServer(serverConfig, c.logger, c.itemsController, c.authController, c.jwtMiddleware) return nil } // Getters for infrastructure func (c *Container) GetLogger() interfaces.ILogger { return c.logger } func (c *Container) GetTimeProvider() interfaces.ITimeProvider { return c.timeProvider } func (c *Container) GetAuthService() interfaces.IAuthService { return c.authService } // Getters for domain func (c *Container) GetExpirationSpec() *specifications.ItemExpirationSpec { return c.expirationSpec } // Getters for application func (c *Container) GetAddItemCommand() *commands.AddItemCommand { return c.addItemCommand } func (c *Container) GetDeleteItemCommand() *commands.DeleteItemCommand { return c.deleteItemCommand } func (c *Container) GetHandleExpiredItemsCommand() *commands.HandleExpiredItemsCommand { return c.handleExpiredItemsCommand } func (c *Container) GetLoginUserCommand() *commands.LoginUserCommand { return c.loginUserCommand } func (c *Container) GetGetItemQuery() *queries.GetItemQuery { return c.getItemQuery } func (c *Container) GetListItemsQuery() *queries.ListItemsQuery { return c.listItemsQuery } // Getters for presentation func (c *Container) GetItemsController() *controllers.ItemsController { return c.itemsController } func (c *Container) GetAuthController() *controllers.AuthController { return c.authController } func (c *Container) GetJWTMiddleware() *middleware.JWTMiddleware { return c.jwtMiddleware } func (c *Container) GetServer() *server.Server { return c.server } func (c *Container) GetExpiredItemsScheduler() *scheduler.ExpiredItemsScheduler { return c.expiredItemsScheduler }