package notify

import (
	"context"
	"fmt"
	"sync"

	"github.com/tidbcloud/infra-provider/infra-inspector/api"
	"github.com/tidbcloud/infra-provider/infra-inspector/pkg/config"

	"github.com/go-logr/logr"
)

type Reporter interface {
	Report(context.Context, *api.Result) error
}

type Notifier struct {
	reporters []Reporter
}

func NewNotifier(config config.NotifyConfig) (*Notifier, error) {
	n := &Notifier{
		reporters: []Reporter{},
	}

	if config.Metric != nil {
		r, err := NewMetricReporter(config.Metric)
		if err != nil {
			return nil, fmt.Errorf("failed to create metric reporter: %v", err)
		}
		n.reporters = append(n.reporters, r)
	}
	if config.PubSub != nil {
		r, err := NewPubSubReporter(config.PubSub)
		if err != nil {
			return nil, fmt.Errorf("failed to create pubsub reporter: %v", err)
		}
		n.reporters = append(n.reporters, r)
	}

	return n, nil
}

func (n *Notifier) Notify(ctx context.Context, result *api.Result) {
	logger := logr.FromContextOrDiscard(ctx).WithName("Notify")

	wg := sync.WaitGroup{}
	wg.Add(len(n.reporters))

	for i := range n.reporters {
		go func(r Reporter) {
			err := r.Report(ctx, result)
			if err != nil {
				logger.Error(err, "failed to report result")
			}
			wg.Done()
		}(n.reporters[i])
	}
	wg.Wait()
}
