// Package register composes the production domain-neutral module family.
package register

import (
	"fmt"

	"gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/semanticreconcile"
	"gitea.maximumdirect.net/eric/notarius/internal/modules/generic/chunk/units"
	jsonoutput "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/output/json"
	alwaysaccept "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/always_accept"
	alwaysreject "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/always_reject"
	validjson "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/valid_json"
	validjsonschema "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/validate/valid_json_schema"
)

// Register adds all production domain-neutral modules and validators.
func Register(registries pipeline.Registries, assets *llm.AssetRegistry) error {
	if err := validateRegistries(registries); err != nil {
		return err
	}
	if assets == nil {
		return fmt.Errorf("generic registrar: asset registry must not be nil")
	}
	registrations := []struct {
		name     string
		register func() error
	}{
		{name: "semantic reconciliation assets", register: func() error { return semanticreconcile.RegisterAssets(assets) }},
		{name: "generic chunker", register: func() error { return units.Register(registries.Chunkers) }},
		{name: "always accept validator", register: func() error { return alwaysaccept.Register(registries.Validators) }},
		{name: "always reject validator", register: func() error { return alwaysreject.Register(registries.Validators) }},
		{name: "valid json validator", register: func() error { return validjson.Register(registries.Validators) }},
		{name: "valid json schema validator", register: func() error { return validjsonschema.Register(registries.Validators) }},
		{name: "json output encoder", register: func() error { return jsonoutput.Register(registries.Outputs) }},
	}
	for _, registration := range registrations {
		if err := registration.register(); err != nil {
			return fmt.Errorf("register %s: %w", registration.name, err)
		}
	}
	return nil
}

func validateRegistries(registries pipeline.Registries) error {
	switch {
	case registries.Chunkers == nil:
		return fmt.Errorf("generic registrar: chunker registry must not be nil")
	case registries.Mergers == nil:
		return fmt.Errorf("generic registrar: merger registry must not be nil")
	case registries.Normalizers == nil:
		return fmt.Errorf("generic registrar: normalizer registry must not be nil")
	case registries.Validators == nil:
		return fmt.Errorf("generic registrar: validator registry must not be nil")
	case registries.Outputs == nil:
		return fmt.Errorf("generic registrar: output registry must not be nil")
	default:
		return nil
	}
}
