package database

import (
	"context"
	"testing"

	"git.anthrove.art/Anthrove/otter-space-sdk/v6/pkg/models"
	"git.anthrove.art/Anthrove/otter-space-sdk/v6/test"
	"go.opentelemetry.io/contrib/bridges/otellogrus"
	"go.opentelemetry.io/otel"
	"gorm.io/gorm"
)

func TestConnect(t *testing.T) {
	// Setup trow away container
	ctx := context.Background()
	container, _, err := test.StartPostgresContainer(ctx)
	if err != nil {
		t.Fatalf("Could not start PostgreSQL container: %v", err)
	}

	defer container.Terminate(ctx)

	// -- -- Setup Tests

	// -- Create Database config to test with
	validDatabaseConfig, err := test.DatabaseModesFromConnectionString(ctx, container)
	if err != nil {
		t.Fatalf("Could not get valid database config: %v", err)
	}
	// --

	// -- -- Tests
	type args struct {
		ctx    context.Context
		config models.DatabaseConfig
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name: "Test 01: Valid DatabaseConfig",
			args: args{
				ctx:    ctx,
				config: validDatabaseConfig,
			},
			wantErr: false,
		},
		{
			name: "Test 02: invalid DatabaseConfig",
			args: args{
				ctx:    ctx,
				config: models.DatabaseConfig{},
			},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := Connect(tt.args.ctx, tt.args.config); (err != nil) != tt.wantErr {
				t.Errorf("Connect() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestGetGorm(t *testing.T) {
	// Setup trow away container
	ctx := context.Background()
	container, _, err := test.StartPostgresContainer(ctx)
	if err != nil {
		t.Fatalf("Could not start PostgreSQL container: %v", err)
	}

	defer container.Terminate(ctx)

	// -- -- Setup Tests

	// -- Create Database config to test with
	validDatabaseConfig, err := test.DatabaseModesFromConnectionString(ctx, container)
	if err != nil {
		t.Fatalf("Could not get valid database config: %v", err)
	}

	err = Connect(ctx, validDatabaseConfig)
	if err != nil {
		t.Fatalf("Could not connect to valid database: %v", err)
	}
	// --

	// -- -- Tests
	type args struct {
		ctx context.Context
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name: "Test 01: GetGorm",
			args: args{
				ctx: ctx,
			},
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			_, err := GetGorm(tt.args.ctx)
			if (err == nil) != !tt.wantErr {
				t.Errorf("GetGorm() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func Test_migrateDatabase(t *testing.T) {
	// Setup trow away container
	ctx := context.Background()
	container, gormDB, err := test.StartPostgresContainer(ctx)
	if err != nil {
		t.Fatalf("Could not start PostgreSQL container: %v", err)
	}

	// Setup open telemetry
	tracer = otel.Tracer(tracingName)

	hook := otellogrus.NewHook(tracingName)
	logger.AddHook(hook)

	defer container.Terminate(ctx)

	// -- -- Setup Tests

	// -- Create Database config to test with
	validDatabaseConfig, err := test.DatabaseModesFromConnectionString(ctx, container)
	if err != nil {
		t.Fatalf("Could not get valid database config: %v", err)
	}
	validDatabaseConfig.Debug = true
	// --

	// -- -- Tests
	type args struct {
		ctx    context.Context
		dbPool *gorm.DB
		config models.DatabaseConfig
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name: "Test 01: MigrateDatabase",
			args: args{
				ctx:    ctx,
				dbPool: gormDB,
				config: validDatabaseConfig,
			},
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := migrateDatabase(tt.args.ctx, tt.args.dbPool, tt.args.config); (err != nil) != tt.wantErr {
				t.Errorf("migrateDatabase() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}