// Code generated by Wire. DO NOT EDIT.

//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

import (
	"context"
	"github.com/Wei-Shaw/sub2api/internal/config"
	"github.com/Wei-Shaw/sub2api/internal/handler"
	"github.com/Wei-Shaw/sub2api/internal/handler/admin"
	"github.com/Wei-Shaw/sub2api/internal/infrastructure"
	"github.com/Wei-Shaw/sub2api/internal/repository"
	"github.com/Wei-Shaw/sub2api/internal/server"
	"github.com/Wei-Shaw/sub2api/internal/service"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
	"log"
	"net/http"
	"time"
)

import (
	_ "embed"
)

// Injectors from wire.go:

func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
	configConfig, err := config.ProvideConfig()
	if err != nil {
		return nil, err
	}
	db, err := infrastructure.ProvideDB(configConfig)
	if err != nil {
		return nil, err
	}
	userRepository := repository.NewUserRepository(db)
	settingRepository := repository.NewSettingRepository(db)
	settingService := service.NewSettingService(settingRepository, configConfig)
	client := infrastructure.ProvideRedis(configConfig)
	emailCache := repository.NewEmailCache(client)
	emailService := service.NewEmailService(settingRepository, emailCache)
	turnstileVerifier := repository.NewTurnstileVerifier()
	turnstileService := service.NewTurnstileService(settingService, turnstileVerifier)
	emailQueueService := service.ProvideEmailQueueService(emailService)
	authService := service.NewAuthService(userRepository, configConfig, settingService, emailService, turnstileService, emailQueueService)
	authHandler := handler.NewAuthHandler(authService)
	userService := service.NewUserService(userRepository)
	userHandler := handler.NewUserHandler(userService)
	apiKeyRepository := repository.NewApiKeyRepository(db)
	groupRepository := repository.NewGroupRepository(db)
	userSubscriptionRepository := repository.NewUserSubscriptionRepository(db)
	apiKeyCache := repository.NewApiKeyCache(client)
	apiKeyService := service.NewApiKeyService(apiKeyRepository, userRepository, groupRepository, userSubscriptionRepository, apiKeyCache, configConfig)
	apiKeyHandler := handler.NewAPIKeyHandler(apiKeyService)
	usageLogRepository := repository.NewUsageLogRepository(db)
	usageService := service.NewUsageService(usageLogRepository, userRepository)
	usageHandler := handler.NewUsageHandler(usageService, apiKeyService)
	redeemCodeRepository := repository.NewRedeemCodeRepository(db)
	billingCache := repository.NewBillingCache(client)
	billingCacheService := service.NewBillingCacheService(billingCache, userRepository, userSubscriptionRepository)
	subscriptionService := service.NewSubscriptionService(groupRepository, userSubscriptionRepository, billingCacheService)
	redeemCache := repository.NewRedeemCache(client)
	redeemService := service.NewRedeemService(redeemCodeRepository, userRepository, subscriptionService, redeemCache, billingCacheService)
	redeemHandler := handler.NewRedeemHandler(redeemService)
	subscriptionHandler := handler.NewSubscriptionHandler(subscriptionService)
	dashboardService := service.NewDashboardService(usageLogRepository)
	dashboardHandler := admin.NewDashboardHandler(dashboardService)
	accountRepository := repository.NewAccountRepository(db)
	proxyRepository := repository.NewProxyRepository(db)
	proxyExitInfoProber := repository.NewProxyExitInfoProber()
	adminService := service.NewAdminService(userRepository, groupRepository, accountRepository, proxyRepository, apiKeyRepository, redeemCodeRepository, billingCacheService, proxyExitInfoProber)
	adminUserHandler := admin.NewUserHandler(adminService)
	groupHandler := admin.NewGroupHandler(adminService)
	claudeOAuthClient := repository.NewClaudeOAuthClient()
	oAuthService := service.NewOAuthService(proxyRepository, claudeOAuthClient)
	openAIOAuthClient := repository.NewOpenAIOAuthClient()
	openAIOAuthService := service.NewOpenAIOAuthService(proxyRepository, openAIOAuthClient)
	geminiOAuthClient := repository.NewGeminiOAuthClient(configConfig)
	geminiCliCodeAssistClient := repository.NewGeminiCliCodeAssistClient()
	geminiOAuthService := service.NewGeminiOAuthService(proxyRepository, geminiOAuthClient, geminiCliCodeAssistClient, configConfig)
	rateLimitService := service.NewRateLimitService(accountRepository, configConfig)
	claudeUsageFetcher := repository.NewClaudeUsageFetcher()
	accountUsageService := service.NewAccountUsageService(accountRepository, usageLogRepository, claudeUsageFetcher)
	geminiTokenCache := repository.NewGeminiTokenCache(client)
	geminiTokenProvider := service.NewGeminiTokenProvider(accountRepository, geminiTokenCache, geminiOAuthService)
	httpUpstream := repository.NewHTTPUpstream(configConfig)
	accountTestService := service.NewAccountTestService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, geminiTokenProvider, httpUpstream)
	concurrencyCache := repository.NewConcurrencyCache(client)
	concurrencyService := service.NewConcurrencyService(concurrencyCache)
	crsSyncService := service.NewCRSSyncService(accountRepository, proxyRepository, oAuthService, openAIOAuthService, geminiOAuthService)
	accountHandler := admin.NewAccountHandler(adminService, oAuthService, openAIOAuthService, geminiOAuthService, rateLimitService, accountUsageService, accountTestService, concurrencyService, crsSyncService)
	oAuthHandler := admin.NewOAuthHandler(oAuthService)
	openAIOAuthHandler := admin.NewOpenAIOAuthHandler(openAIOAuthService, adminService)
	geminiOAuthHandler := admin.NewGeminiOAuthHandler(geminiOAuthService)
	proxyHandler := admin.NewProxyHandler(adminService)
	adminRedeemHandler := admin.NewRedeemHandler(adminService)
	settingHandler := admin.NewSettingHandler(settingService, emailService)
	updateCache := repository.NewUpdateCache(client)
	gitHubReleaseClient := repository.NewGitHubReleaseClient()
	serviceBuildInfo := provideServiceBuildInfo(buildInfo)
	updateService := service.ProvideUpdateService(updateCache, gitHubReleaseClient, serviceBuildInfo)
	systemHandler := handler.ProvideSystemHandler(updateService)
	adminSubscriptionHandler := admin.NewSubscriptionHandler(subscriptionService)
	adminUsageHandler := admin.NewUsageHandler(usageService, apiKeyService, adminService)
	adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, proxyHandler, adminRedeemHandler, settingHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler)
	gatewayCache := repository.NewGatewayCache(client)
	pricingRemoteClient := repository.NewPricingRemoteClient()
	pricingService, err := service.ProvidePricingService(configConfig, pricingRemoteClient)
	if err != nil {
		return nil, err
	}
	billingService := service.NewBillingService(configConfig, pricingService)
	identityCache := repository.NewIdentityCache(client)
	identityService := service.NewIdentityService(identityCache)
	gatewayService := service.NewGatewayService(accountRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, billingService, rateLimitService, billingCacheService, identityService, httpUpstream)
	geminiMessagesCompatService := service.NewGeminiMessagesCompatService(accountRepository, gatewayCache, geminiTokenProvider, rateLimitService, httpUpstream)
	gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, userService, concurrencyService, billingCacheService)
	openAIGatewayService := service.NewOpenAIGatewayService(accountRepository, usageLogRepository, userRepository, userSubscriptionRepository, gatewayCache, configConfig, billingService, rateLimitService, billingCacheService, httpUpstream)
	openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService)
	handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo)
	handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler)
	groupService := service.NewGroupService(groupRepository)
	accountService := service.NewAccountService(accountRepository, groupRepository)
	proxyService := service.NewProxyService(proxyRepository)
	tokenRefreshService := service.ProvideTokenRefreshService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, configConfig)
	services := &service.Services{
		Auth:          authService,
		User:          userService,
		ApiKey:        apiKeyService,
		Group:         groupService,
		Account:       accountService,
		Proxy:         proxyService,
		Redeem:        redeemService,
		Usage:         usageService,
		Pricing:       pricingService,
		Billing:       billingService,
		BillingCache:  billingCacheService,
		Admin:         adminService,
		Gateway:       gatewayService,
		OpenAIGateway: openAIGatewayService,
		OAuth:         oAuthService,
		OpenAIOAuth:   openAIOAuthService,
		GeminiOAuth:   geminiOAuthService,
		RateLimit:     rateLimitService,
		AccountUsage:  accountUsageService,
		AccountTest:   accountTestService,
		Setting:       settingService,
		Email:         emailService,
		EmailQueue:    emailQueueService,
		Turnstile:     turnstileService,
		Subscription:  subscriptionService,
		Concurrency:   concurrencyService,
		Identity:      identityService,
		Update:        updateService,
		TokenRefresh:  tokenRefreshService,
	}
	repositories := &repository.Repositories{
		User:             userRepository,
		ApiKey:           apiKeyRepository,
		Group:            groupRepository,
		Account:          accountRepository,
		Proxy:            proxyRepository,
		RedeemCode:       redeemCodeRepository,
		UsageLog:         usageLogRepository,
		Setting:          settingRepository,
		UserSubscription: userSubscriptionRepository,
	}
	engine := server.ProvideRouter(configConfig, handlers, services, repositories)
	httpServer := server.ProvideHTTPServer(configConfig, engine)
	v := provideCleanup(db, client, services)
	application := &Application{
		Server:  httpServer,
		Cleanup: v,
	}
	return application, nil
}

// wire.go:

type Application struct {
	Server  *http.Server
	Cleanup func()
}

func provideServiceBuildInfo(buildInfo handler.BuildInfo) service.BuildInfo {
	return service.BuildInfo{
		Version:   buildInfo.Version,
		BuildType: buildInfo.BuildType,
	}
}

func provideCleanup(
	db *gorm.DB,
	rdb *redis.Client,
	services *service.Services,
) func() {
	return func() {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()

		cleanupSteps := []struct {
			name string
			fn   func() error
		}{
			{"TokenRefreshService", func() error {
				services.TokenRefresh.Stop()
				return nil
			}},
			{"PricingService", func() error {
				services.Pricing.Stop()
				return nil
			}},
			{"EmailQueueService", func() error {
				services.EmailQueue.Stop()
				return nil
			}},
			{"OAuthService", func() error {
				services.OAuth.Stop()
				return nil
			}},
			{"OpenAIOAuthService", func() error {
				services.OpenAIOAuth.Stop()
				return nil
			}},
			{"GeminiOAuthService", func() error {
				services.GeminiOAuth.Stop()
				return nil
			}},
			{"Redis", func() error {
				return rdb.Close()
			}},
			{"Database", func() error {
				sqlDB, err := db.DB()
				if err != nil {
					return err
				}
				return sqlDB.Close()
			}},
		}

		for _, step := range cleanupSteps {
			if err := step.fn(); err != nil {
				log.Printf("[Cleanup] %s failed: %v", step.name, err)

			} else {
				log.Printf("[Cleanup] %s succeeded", step.name)
			}
		}

		select {
		case <-ctx.Done():
			log.Printf("[Cleanup] Warning: cleanup timed out after 10 seconds")
		default:
			log.Printf("[Cleanup] All cleanup steps completed")
		}
	}
}
