package cmd

import (
	"context"
	"errors"
	"fmt"
	"log/slog"
	"os"

	"github.com/alecthomas/kong"

	"code.icb4dc0.de/prskr/pg_v_man/infrastructure/config"
	"code.icb4dc0.de/prskr/pg_v_man/infrastructure/db"
	"code.icb4dc0.de/prskr/pg_v_man/infrastructure/rabbitmq"
)

func RunApp(ctx context.Context) error {
	var app App

	return kong.Parse(
		&app,
		kong.Name("replication-emitter"),
		kong.BindTo(ctx, (*context.Context)(nil)),
	).Run()
}

type App struct {
	Logging  config.Logging  `embed:"" prefix:"logging."`
	DB       config.DB       `embed:"" prefix:"db."`
	RabbitMQ config.RabbitMQ `embed:"" prefix:"rabbitmq."`
}

func (a *App) Run(ctx context.Context) (err error) {
	publisher, err := rabbitmq.NewPublishingEventConsumer(ctx, a.RabbitMQ)
	if err != nil {
		return fmt.Errorf("could not create publishing event consumer: %w", err)
	}

	replClient, err := db.NewReplicationClient(ctx, a.DB, publisher)
	if err != nil {
		return fmt.Errorf("could not create replication client: %w", err)
	}

	defer func() {
		err = errors.Join(err, replClient.Close(context.Background()))
	}()

	return replClient.Receive(ctx)
}

func (a *App) AfterApply(kongCtx *kong.Context) error {
	defaultLogger := slog.New(slog.NewJSONHandler(os.Stderr, a.Logging.Options()))

	slog.SetDefault(defaultLogger)

	kongCtx.Bind(defaultLogger)

	return nil
}