package daemon

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/spf13/cobra"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"

	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/app"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/storage/database"
)

// createBootstrapLogger creates a simple console logger for use during application bootstrap
// This is used before the main application logger is initialized
func createBootstrapLogger() *zap.Logger {
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "ts",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "",
		FunctionKey:    zapcore.OmitKey,
		MessageKey:     "msg",
		StacktraceKey:  "",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalColorLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}

	core := zapcore.NewCore(
		zapcore.NewConsoleEncoder(encoderConfig),
		zapcore.AddSync(os.Stdout),
		zapcore.InfoLevel,
	)

	return zap.New(core)
}

// DaemonCmd returns the daemon command
func DaemonCmd() *cobra.Command {
	var noAutoMigrate bool

	cmd := &cobra.Command{
		Use:   "daemon",
		Short: "Start the MaplePress backend server",
		Long: `Start the MaplePress backend server.

By default, the server will automatically run database migrations on startup.
This ensures the database schema is always up-to-date with the application code.

For cloud-native deployments (Kubernetes, Docker, etc.), this is the recommended approach.
To disable auto-migration, use the --no-auto-migrate flag.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			// Create bootstrap logger for startup messages
			logger := createBootstrapLogger()
			defer logger.Sync()

			// Load configuration
			cfg, err := config.Load()
			if err != nil {
				return err
			}

			// Run migrations automatically (unless disabled)
			if !noAutoMigrate {
				logger.Info("⏳ Running database migrations...")
				migrator := database.NewMigrator(cfg, logger)
				if err := migrator.Up(); err != nil {
					return fmt.Errorf("failed to run migrations: %w", err)
				}
				logger.Info("✓ Database migrations completed successfully")
			} else {
				logger.Warn("⚠️  Auto-migration disabled, skipping database migrations")
			}

			// Initialize application via Wire
			logger.Info("⏳ Initializing application dependencies...")
			application, err := app.InitializeApplication(cfg)
			if err != nil {
				return err
			}
			logger.Info("✓ Application dependencies initialized")
			logger.Info("")

			// Start server
			ctx, cancel := context.WithCancel(context.Background())
			defer cancel()

			// Handle graceful shutdown
			sigChan := make(chan os.Signal, 1)
			signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)

			errChan := make(chan error, 1)
			go func() {
				errChan <- application.Run(ctx)
			}()

			select {
			case err := <-errChan:
				return err
			case <-sigChan:
				return application.Shutdown(ctx)
			}
		},
	}

	// Add flags
	cmd.Flags().BoolVar(&noAutoMigrate, "no-auto-migrate", false, "Disable automatic database migrations on startup")

	return cmd
}
