package telemetry_test

import (
	"errors"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.opentelemetry.io/otel/exporters/prometheus"
	"go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/metric/noop"
	sdkmetric "go.opentelemetry.io/otel/sdk/metric"
	"go.opentelemetry.io/otel/sdk/resource"

	"github.com/agentregistry-dev/agentregistry/internal/registry/telemetry"
)

func TestNewMetrics(t *testing.T) {
	tests := []struct {
		name           string
		meter          metric.Meter
		expectedMetric string
		expectedError  error
	}{
		{
			name:           "Valid Meter",
			meter:          noop.NewMeterProvider().Meter("test"),
			expectedMetric: "http_requests_total",
			expectedError:  nil,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			metrics, err := telemetry.NewMetrics(tt.meter)

			// Ensure the metric is registered correctly
			require.NoError(t, err)
			assert.NotNil(t, metrics)
			assert.NotNil(t, metrics.Requests)
		})
	}
}

func TestNewPrometheusMeterProvider(t *testing.T) {
	tests := []struct {
		name           string
		wantErr        bool
		mockPrometheus func() (*prometheus.Exporter, error)
		expectedError  error
	}{
		{
			name:    "Successful creation of meter provider",
			wantErr: false,
			mockPrometheus: func() (*prometheus.Exporter, error) {
				return &prometheus.Exporter{
					Reader: sdkmetric.NewManualReader(),
				}, nil
			},
		},
		{
			name:          "Error on resource creation",
			wantErr:       true,
			expectedError: errors.New("error creating prometheus resource"),
			mockPrometheus: func() (*prometheus.Exporter, error) {
				return nil, errors.New("error creating prometheus resource")
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			res := resource.NewSchemaless() // Use an empty resource for testing.
			exp, _ := tt.mockPrometheus()
			mp, err := telemetry.NewPrometheusMeterProvider(res, exp)

			if tt.wantErr {
				require.Error(t, err)
			} else {
				require.NoError(t, err)
				assert.NotNil(t, mp)
			}
		})
	}
}
