package admin

import (
	"context"
	"fmt"

	"galaxy/backend/internal/config"

	"go.uber.org/zap"
	"golang.org/x/crypto/bcrypt"
)

// Bootstrap inserts the seed admin row when the env-driven
// `BACKEND_ADMIN_BOOTSTRAP_USER` / `BACKEND_ADMIN_BOOTSTRAP_PASSWORD`
// values are supplied and no row with that username exists yet. The
// insert is idempotent across restarts so operators can leave the env
// vars set after the first deploy without re-creating the row on
// every boot.
//
// Bootstrap runs *before* `Cache.Warm` so the warm read picks up the
// seed row. Errors are returned to the caller; the boot path in
// `cmd/backend/main.go` aborts startup if Bootstrap fails (a missing
// admin would lock the surface out anyway, so failing fast is the
// safer default).
//
// When both env vars are empty the function logs "skipped" and
// returns nil. `config.Validate()` already enforces that the username
// and password are set together, so by the time Bootstrap runs the
// remaining "user set without password" combination is impossible.
func Bootstrap(ctx context.Context, store *Store, cfg config.AdminBootstrapConfig, logger *zap.Logger) error {
	if logger == nil {
		logger = zap.NewNop()
	}
	logger = logger.Named("admin.bootstrap")

	if cfg.User == "" {
		logger.Info("skipped (no env vars)")
		return nil
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(cfg.Password), bootstrapBcryptCost)
	if err != nil {
		return fmt.Errorf("admin bootstrap: hash password: %w", err)
	}

	inserted, err := store.BootstrapInsert(ctx, cfg.User, hash)
	if err != nil {
		return fmt.Errorf("admin bootstrap: %w", err)
	}
	if inserted {
		logger.Info("inserted seed admin", zap.String("admin_username", cfg.User))
	} else {
		logger.Info("skipped (admin exists)", zap.String("admin_username", cfg.User))
	}
	return nil
}
