// 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 app

import (
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/maplefile/client"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/pkg/storage/leveldb"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/config"
	session2 "codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/domain/session"
	session3 "codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/repo/session"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/auth"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/httpclient"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/keycache"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/passwordstore"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/ratelimiter"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/search"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/securitylog"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/storagemanager"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/sync"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/tokenmanager"
	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/usecase/session"
	"context"
	"go.uber.org/zap"
	"os"
	"strings"
)

// Injectors from wire.go:

// InitializeApplication creates a fully configured Application using Wire DI
func InitializeApplication() (*Application, error) {
	logger, err := ProvideLogger()
	if err != nil {
		return nil, err
	}
	configService, err := config.New()
	if err != nil {
		return nil, err
	}
	client, err := ProvideMapleFileClient(configService, logger)
	if err != nil {
		return nil, err
	}
	repository, err := ProvideSessionRepository(logger)
	if err != nil {
		return nil, err
	}
	createUseCase := session.ProvideCreateUseCase(repository)
	getByIdUseCase := session.ProvideGetByIdUseCase(repository)
	deleteUseCase := session.ProvideDeleteUseCase(repository)
	saveUseCase := session.ProvideSaveUseCase(repository)
	service := auth.ProvideService(client, createUseCase, getByIdUseCase, deleteUseCase, saveUseCase, logger)
	manager := tokenmanager.ProvideManager(client, service, getByIdUseCase, logger)
	passwordstoreService := passwordstore.ProvideService(logger)
	keycacheService := keycache.ProvideService(logger)
	ratelimiterService := ratelimiter.ProvideService()
	httpclientService := httpclient.ProvideService()
	storagemanagerManager := storagemanager.ProvideManager(logger)
	collectionSyncService := sync.ProvideCollectionSyncService(logger, client, storagemanagerManager)
	fileSyncService := sync.ProvideFileSyncService(logger, client, storagemanagerManager)
	syncService := sync.ProvideService(logger, collectionSyncService, fileSyncService, storagemanagerManager)
	securitylogService := securitylog.ProvideService(logger)
	searchService := search.New(configService, logger)
	application := ProvideApplication(logger, configService, service, manager, passwordstoreService, keycacheService, ratelimiterService, httpclientService, syncService, storagemanagerManager, securitylogService, searchService)
	return application, nil
}

// wire.go:

// ProvideLogger creates the application logger with environment-aware configuration.
// Defaults to production mode for security. Development mode must be explicitly enabled.
func ProvideLogger() (*zap.Logger, error) {
	mode := os.Getenv("MAPLEFILE_MODE")

	if mode == "dev" || mode == "development" {

		return zap.NewDevelopment()
	}

	cfg := zap.NewProductionConfig()
	cfg.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
	cfg.DisableCaller = true
	cfg.DisableStacktrace = true
	return cfg.Build()
}

// ProvideSessionRepository creates the session repository with its storage.
// Session storage is GLOBAL (not user-specific) because it stores the current login session.
func ProvideSessionRepository(logger *zap.Logger) (session2.Repository, error) {
	provider, err := config.NewLevelDBConfigurationProviderForSession()
	if err != nil {
		return nil, err
	}
	sessionStorage := leveldb.NewDiskStorage(provider, logger.Named("session-storage"))
	return session3.ProvideRepository(sessionStorage), nil
}

// zapLoggerAdapter adapts *zap.Logger to client.Logger interface
type zapLoggerAdapter struct {
	logger *zap.Logger
}

func (a *zapLoggerAdapter) Debug(msg string, keysAndValues ...interface{}) {
	fields := keysAndValuesToZapFields(keysAndValues...)
	a.logger.Debug(msg, fields...)
}

func (a *zapLoggerAdapter) Info(msg string, keysAndValues ...interface{}) {
	fields := keysAndValuesToZapFields(keysAndValues...)
	a.logger.Info(msg, fields...)
}

func (a *zapLoggerAdapter) Warn(msg string, keysAndValues ...interface{}) {
	fields := keysAndValuesToZapFields(keysAndValues...)
	a.logger.Warn(msg, fields...)
}

func (a *zapLoggerAdapter) Error(msg string, keysAndValues ...interface{}) {
	fields := keysAndValuesToZapFields(keysAndValues...)
	a.logger.Error(msg, fields...)
}

// keysAndValuesToZapFields converts key-value pairs to zap fields
func keysAndValuesToZapFields(keysAndValues ...interface{}) []zap.Field {
	fields := make([]zap.Field, 0, len(keysAndValues)/2)
	for i := 0; i+1 < len(keysAndValues); i += 2 {
		key, ok := keysAndValues[i].(string)
		if !ok {
			continue
		}
		fields = append(fields, zap.Any(key, keysAndValues[i+1]))
	}
	return fields
}

// BuildMode is set at compile time via -ldflags
// Example: go build -ldflags "-X codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/app.BuildMode=dev"
var BuildMode string

// ProvideMapleFileClient creates the backend API client
func ProvideMapleFileClient(configService config.ConfigService, logger *zap.Logger) (*client.Client, error) {
	ctx := context.Background()

	mode := os.Getenv("MAPLEFILE_MODE")

	logger.Info("Startup: checking mode configuration", zap.String("MAPLEFILE_MODE_env", mode), zap.String("BuildMode_compile_time", BuildMode))

	if mode == "" {
		if BuildMode != "" {
			mode = BuildMode
			logger.Info("Startup: using compile-time BuildMode", zap.String("mode", mode))
		} else {
			mode = "production"
			logger.Info("Startup: no mode set, defaulting to production", zap.String("mode", mode))
		}
	}

	var baseURL string
	switch mode {
	case "production":
		baseURL = client.ProductionURL
	case "dev", "development":
		baseURL = client.LocalURL
	default:

		cfg, err := configService.GetConfig(ctx)
		if err != nil {
			return nil, err
		}
		baseURL = cfg.CloudProviderAddress
	}

	clientLogger := &zapLoggerAdapter{logger: logger.Named("api-client")}

	apiClient := client.New(client.Config{
		BaseURL: baseURL,
		Logger:  clientLogger,
	})

	logger.Info("MapleFile API client initialized", zap.String("mode", mode), zap.String("base_url", baseURL))

	if strings.HasPrefix(baseURL, "http://") {
		logger.Warn("SECURITY WARNING: Using unencrypted HTTP connection", zap.String("mode", mode), zap.String("base_url", baseURL), zap.String("recommendation", "This should only be used for local development"))
	}

	if mode != "production" {
		if err := configService.SetCloudProviderAddress(ctx, baseURL); err != nil {
			logger.Warn("Failed to update cloud provider address in config", zap.Error(err))
		}
	}

	return apiClient, nil
}
