package api

import (
	"context"
	"errors"
	"testing"

	mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
	"github.com/google/uuid"
	guuid "github.com/google/uuid"
	"github.com/openconfig/gnmi/proto/gnmi"
	"github.com/openconfig/ygot/ygot"
	"github.com/spf13/viper"
)

// This functions complexity is too high, but this will be addresses once the
// TestSetup is refactored.
//
//nolint:gocyclo
func TestApiIntegration(t *testing.T) {
	// TDOO: Remove once openshift grpc support is available
	t.Skip("skipped due to openshift limitations")
	if testing.Short() {
		t.Skip("skipping integration test")
	}

	path, err := ygot.StringToStructuredPath(testPath)
	if err != nil {
		t.Error(err)
	}

	tests := []struct {
		name    string
		wantErr bool
	}{
		{
			name:    "default",
			wantErr: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			defer viper.Reset()
			if err := Init(context.TODO(), testAPIEndpoint); (err != nil) != tt.wantErr {
				if errors.As(err, &viper.ConfigFileNotFoundError{}) {
					t.Errorf("gosdn cli init error = %v, wantErr %v", err, tt.wantErr)
					return
				}
			}
			cliPnd := viper.GetString("CLI_PND")
			cliSbi := viper.GetString("CLI_SBI")

			suid, err := uuid.Parse(cliSbi)
			if err != nil {
				t.Error(err)
			}
			puid, err := uuid.Parse(cliPnd)
			if err != nil {
				t.Error(err)
			}

			opt := &tpb.TransportOption{
				Address:  testAddress,
				Username: testUsername,
				Password: testPassword,
				TransportOption: &tpb.TransportOption_GnmiTransportOption{
					GnmiTransportOption: &tpb.GnmiTransportOption{},
				},
			}
			if _, err := AddNetworkElement(
				context.TODO(),
				testAPIEndpoint,
				"test-networkElement",
				opt,
				suid,
				puid,
			); (err != nil) != tt.wantErr {
				t.Errorf("gosdn cli add-networkElement error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			mneid := viper.GetString("LAST_NETWORK_ELEMENT_UUID")

			_, err = GetNetworkElement(
				context.TODO(),
				testAPIEndpoint,
				cliPnd,
				mneid,
			)
			if (err != nil) != tt.wantErr {
				t.Errorf("gosdn cli request error = %v, wantErr %v", err, tt.wantErr)
				return
			}

			_, err = GetNetworkElement(
				context.TODO(),
				testAPIEndpoint,
				cliPnd,
				mneid,
			)
			if (err != nil) != tt.wantErr {
				t.Errorf("gosdn cli get-networkElement error = %v, wantErr %v", err, tt.wantErr)
				return
			}

			hostname := guuid.New().String()
			hostnameAsTypedValue := &gnmi.TypedValue{
				Value: &gnmi.TypedValue_StringVal{
					StringVal: hostname,
				},
			}
			_, err = ChangeRequest(
				context.TODO(),
				testAPIEndpoint,
				mneid,
				cliPnd,
				path,
				hostnameAsTypedValue,
				mnepb.ApiOperation_API_OPERATION_UPDATE,
			)
			if (err != nil) != tt.wantErr {
				t.Errorf("gosdn cli set error = %v, wantErr %v", err, tt.wantErr)
				return
			}

			resp, err := GetNetworkElement(context.TODO(), testAddress, testUsername, testPassword)
			if err != nil {
				if !tt.wantErr {
					t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
				}
				return
			}
			var got string
			if resp != nil {
				got = resp.Mne.Name
			} else {
				t.Errorf("integration test failed got cannot be nil")
			}
			if got != hostname {
				t.Errorf("integration test failed = got: %v, want: %v", got, hostname)
			}
		})
	}
}
