package kafka

import (
	"context"
	"fmt"

	"github.com/twmb/franz-go/pkg/kadm"
	"github.com/twmb/franz-go/pkg/kgo"
)

type Deps struct {
	Client *kadm.Client
}

type Kafka struct {
	client *kadm.Client
}

func New(deps Deps) *Kafka {
	return &Kafka{client: deps.Client}
}

func (receiver *Kafka) TopicExists(ctx context.Context, topic string) (bool, error) {
	topicsMetadata, err := receiver.client.ListTopics(ctx)
	if err != nil {
		return false, err
	}

	for _, metadata := range topicsMetadata {
		if metadata.Topic == topic {
			return true, nil
		}
	}

	return false, nil
}

func (receiver *Kafka) CreateTopic(ctx context.Context, topic string) error {
	responses, err := receiver.client.CreateTopics(ctx, 1, 1, nil, topic)
	if err != nil {
		return err
	}

	for _, response := range responses {
		if response.Err != nil {
			return err
		}
	}

	return nil
}

// Initialize topics in brokers if not exist. Client connection closes self.
func Initialize(ctx context.Context, brokers, topics []string) error {
	lastInitializeErr := error(nil)

	kafkaAdminClient, err := kgo.NewClient(kgo.SeedBrokers(brokers...))
	if err != nil {
		return err
	}

	defer kafkaAdminClient.Close()

	kafka := New(Deps{Client: kadm.NewClient(kafkaAdminClient)})

	for _, topic := range topics {
		isExist, err := kafka.TopicExists(ctx, topic)
		if err != nil {
			lastInitializeErr = fmt.Errorf("failed to check is topic <%s> exist on brokers <%+q>: %w", topic, brokers, err)
			continue
		}

		if isExist {
			continue
		}

		if err := kafka.CreateTopic(ctx, topic); err != nil {
			lastInitializeErr = fmt.Errorf("failed to create topic <%s> on brokers <%+q>: %w", topic, brokers, err)
		}
	}

	return lastInitializeErr
}
