package ibm

import (
	"context"
	"errors"
	"testing"

	"github.com/IBM/platform-services-go-sdk/globalcatalogv1"
	"github.com/stretchr/testify/assert"
)

type mockIAMClient struct {
	token string
	err   error
}

func (m *mockIAMClient) GetToken(ctx context.Context) (string, error) {
	return m.token, m.err
}

func TestNewGlobalCatalogClient(t *testing.T) {
	iamClient := &mockIAMClient{token: "test-token"}
	client := NewGlobalCatalogClient(iamClient)

	if client == nil {
		t.Error("expected non-nil client")
	}
	if client.iamClient != iamClient {
		t.Error("expected iamClient to be set")
	}
}

func TestEnsureClient(t *testing.T) {
	tests := []struct {
		name      string
		iamClient *mockIAMClient
		wantErr   bool
	}{
		{
			name:      "successful client initialization",
			iamClient: &mockIAMClient{token: "test-token"},
			wantErr:   false,
		},
		{
			name:      "IAM token error",
			iamClient: &mockIAMClient{err: errors.New("token error")},
			wantErr:   true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			client := NewGlobalCatalogClient(tt.iamClient)
			err := client.ensureClient(context.Background())

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

func TestGetInstanceType(t *testing.T) {
	ctx := context.Background()
	tests := []struct {
		name      string
		id        string
		iamClient *mockIAMClient
		wantErr   bool
	}{
		{
			name:      "valid instance type request",
			id:        "test-instance-id",
			iamClient: &mockIAMClient{token: "test-token"},
			wantErr:   false,
		},
		{
			name:      "IAM token error",
			id:        "test-instance-id",
			iamClient: &mockIAMClient{err: errors.New("token error")},
			wantErr:   true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			client := NewGlobalCatalogClient(tt.iamClient)
			entry, err := client.GetInstanceType(ctx, tt.id)

			if tt.wantErr {
				assert.Error(t, err)
				assert.Nil(t, entry)
			} else {
				// Note: In a real scenario, we would mock the globalcatalogv1.GlobalCatalogV1
				// client and verify the response. Here we just check that the call fails
				// because we're not mocking the actual API call.
				assert.Error(t, err)
			}
		})
	}
}

func TestListInstanceTypes(t *testing.T) {
	ctx := context.Background()
	tests := []struct {
		name      string
		iamClient *mockIAMClient
		wantErr   bool
	}{
		{
			name:      "successful list request",
			iamClient: &mockIAMClient{token: "test-token"},
			wantErr:   false,
		},
		{
			name:      "IAM token error",
			iamClient: &mockIAMClient{err: errors.New("token error")},
			wantErr:   true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			client := NewGlobalCatalogClient(tt.iamClient)
			entries, err := client.ListInstanceTypes(ctx)

			if tt.wantErr {
				assert.Error(t, err)
				assert.Nil(t, entries)
			} else {
				// Note: In a real scenario, we would mock the globalcatalogv1.GlobalCatalogV1
				// client and verify the response. Here we just check that the call fails
				// because we're not mocking the actual API call.
				assert.Error(t, err)
			}
		})
	}
}
