package initialize

import (
	"context"
	"kra/internal/biz/system"
	"kra/internal/config"

	datasystem "kra/internal/data/system"
	datatask "kra/internal/data/task"
	platformmodule "kra/pkg/module"

	"gorm.io/gorm"
)

// Backend is the infrastructure boundary required by application
// initialization and runtime configuration management.
type Backend interface {
	IsInitialized(context.Context) (bool, error)
	InitializeDatabase(context.Context, *system.DatabaseConfig, func(context.Context, *gorm.DB) error) error
	PersistConfig(context.Context) error
	PersistRuntimeConfig(context.Context, *config.Config) error
	ReloadConfig(context.Context) error
	Config() *config.Config
}

// Repo adapts Backend to system.InitializationRepo. Backend is embedded so the
// four identically shaped methods are promoted instead of hand-forwarded; this
// file adds only what the two boundaries genuinely disagree on.
type Repo struct {
	Backend
	catalog platformmodule.Catalog
}

func NewRepo(backend Backend, catalog platformmodule.Catalog) system.InitializationRepo {
	return &Repo{Backend: backend, catalog: catalog}
}

// Initialize layers system and task seeding on top of the backend's database
// lifecycle, which is the one place the two interfaces differ in shape.
func (r *Repo) Initialize(ctx context.Context, input *system.DatabaseConfig) error {
	return r.InitializeDatabase(ctx, input, func(ctx context.Context, db *gorm.DB) error {
		if err := datasystem.SeedSystemWithCatalog(ctx, db, input, r.catalog); err != nil {
			return err
		}
		return datatask.SeedDefaults(ctx, db, r.catalog.DefaultTimedTasks())
	})
}
