package pilgrim_conf_test

import (
	"testing"

	"github.com/stretchr/testify/assert"
	pilgrim_mock "mvvasilev.dev/pilgrim/internal/mocks"
	"mvvasilev.dev/pilgrim/internal/pilgrim_conf"
)

const CliUrlValue = "postgres://cli_host:5432/cli_segment1/cli_segment2?cli_arg1=cli_val1&cli_arg2=cli_val2"
const CliDriverValue = pilgrim_conf.DbDriver_Postgres

func runTest(
	setupMocks func(
		env *pilgrim_mock.EnvVarRetriever,
		cli *pilgrim_mock.CliFlagRetriever,
	),
	test func(
		env *pilgrim_mock.EnvVarRetriever,
		cli *pilgrim_mock.CliFlagRetriever,
	),
) {
	env, cli := new(pilgrim_mock.EnvVarRetriever), new(pilgrim_mock.CliFlagRetriever)

	setupMocks(env, cli)

	env.EXPECT().Url().Return("", false)
	env.EXPECT().Driver().Return(pilgrim_conf.DbDriver_Postgres, false)
	env.EXPECT().Username().Return("", false)
	env.EXPECT().Password().Return("", false)
	env.EXPECT().Host().Return("", false)
	env.EXPECT().Port().Return("", false)
	env.EXPECT().Segments().Return([]string{}, false)
	env.EXPECT().Args().Return(map[string]string{}, false)
	env.EXPECT().Directory().Return("", false)
	env.EXPECT().MigrationTable().Return("", false)
	env.EXPECT().MigrationTableSchema().Return("", false)

	cli.EXPECT().Url().Return("", false)
	cli.EXPECT().Driver().Return(pilgrim_conf.DbDriver_Postgres, false)
	cli.EXPECT().Username().Return("", false)
	cli.EXPECT().Password().Return("", false)
	cli.EXPECT().Host().Return("", false)
	cli.EXPECT().Port().Return("", false)
	cli.EXPECT().Segments().Return([]string{}, false)
	cli.EXPECT().Args().Return(map[string]string{}, false)
	cli.EXPECT().Directory().Return("", false)
	cli.EXPECT().IsUp().Return(false, false)
	cli.EXPECT().IsDown().Return(false, false)
	cli.EXPECT().Script().Return("", false)
	cli.EXPECT().MigrationTable().Return("", false)
	cli.EXPECT().MigrationTableSchema().Return("", false)
	cli.EXPECT().IsChecksumValidationEnabled().Return(false, false)
	cli.EXPECT().IsStrictOrderingEnabled().Return(false, false)
	cli.EXPECT().IsValidatingMigrationOrder().Return(false, false)
	cli.EXPECT().IsValidatingLatest().Return(false, false)
	cli.EXPECT().IsValidatingChecksums().Return(false, false)

	test(env, cli)
}

func Test_PilgrimContext_CliDriverOverridesCliUrlDriver(t *testing.T) {
	runTest(
		func(env *pilgrim_mock.EnvVarRetriever, cli *pilgrim_mock.CliFlagRetriever) {
			env.EXPECT().Driver().Return(pilgrim_conf.DbDriver_MSSQL, true)
			cli.EXPECT().Driver().Return(pilgrim_conf.DbDriver_MySQL, true) // This should be of highest priority
			cli.EXPECT().Url().Return("postgres://cli_host:5432/cli_segment1/cli_segment2?cli_arg1=cli_val1&cli_arg2=cli_val2", true)
		},
		func(env *pilgrim_mock.EnvVarRetriever, cli *pilgrim_mock.CliFlagRetriever) {
			ctx := pilgrim_conf.NewPilgrimContext(cli, env)

			assert.Equal(t, pilgrim_conf.DbDriver_MySQL, ctx.UrlParts().Driver)
		},
	)
}

func Test_PilgrimContext_EnvDriverOverridesEnvUrlDriver(t *testing.T) {
	runTest(
		func(env *pilgrim_mock.EnvVarRetriever, cli *pilgrim_mock.CliFlagRetriever) {
			env.EXPECT().Driver().Return(pilgrim_conf.DbDriver_MSSQL, true) // This should be highest priority
			env.EXPECT().Url().Return("postgres://env_host:5432", true)
		},
		func(env *pilgrim_mock.EnvVarRetriever, cli *pilgrim_mock.CliFlagRetriever) {
			ctx := pilgrim_conf.NewPilgrimContext(cli, env)

			assert.Equal(t, pilgrim_conf.DbDriver_MSSQL, ctx.UrlParts().Driver)
		},
	)
}

// func Test_PilgrimContext_EnvDriverOverridesEnvUrlDriver(t *testing.T) {
// 	context, _, _ := createPilgrimContextWithDependencies(
// 		map[string]string{},
// 		map[string]string{
// 			EnvVarKey_Url:    "mariadb://env_host:3306/env_segment1/env_segment2?env_arg1=env_val1&env_arg2=env_val2",
// 			EnvVarKey_Driver: "postgres",
// 		},
// 	)

// 	assert.Equal(t, DbDriver_Postgres, context.UrlParts().Driver)
// }

// func Test_PilgrimContext_CliUrlDriverOverridesEnvDriver(t *testing.T) {
// 	context, _, _ := createPilgrimContextWithDependencies(
// 		map[string]string{
// 			Flag_Url: CliUrlValue,
// 		},
// 		map[string]string{
// 			EnvVarKey_Driver: "mariadb",
// 		},
// 	)

// 	assert.Equal(t, CliDriverValue, context.UrlParts().Driver)
// }

// func Test_PilgrimContext_CliDriverOverridesEnvDriver(t *testing.T) {
// 	context, _, _ := createPilgrimContextWithDependencies(
// 		map[string]string{
// 			Flag_Driver: string(CliDriverValue),
// 		},
// 		map[string]string{
// 			EnvVarKey_Driver: "mariadb",
// 		},
// 	)

// 	assert.Equal(t, CliDriverValue, context.UrlParts().Driver)
// }

// func Test_PilgrimContext_EnvDriverIsUsedIfNoCliDriverProvided(t *testing.T) {
// 	context, _, _ := createPilgrimContextWithDependencies(
// 		map[string]string{},
// 		map[string]string{
// 			EnvVarKey_Driver: "mariadb",
// 		},
// 	)

// 	assert.Equal(t, DbDriver_MariaDB, context.UrlParts().Driver)
// }

// func Test_PilgrimContext_EnvUrlDriverIsUsedIfNoCliDriverProvided(t *testing.T) {
// 	context, _, _ := createPilgrimContextWithDependencies(
// 		map[string]string{},
// 		map[string]string{
// 			EnvVarKey_Url: "mariadb://env_host:3306/env_segment1/env_segment2?env_arg1=env_val1&env_arg2=env_val2",
// 		},
// 	)

// 	assert.Equal(t, DbDriver_MariaDB, context.UrlParts().Driver)
// }

// func Test_PilgrimContext_EnvUrlDriverIsNotUsedIfNoCliDriverOverrideProvided(t *testing.T) {
// 	context, _, _ := createPilgrimContextWithDependencies(
// 		map[string]string{
// 			Flag_Driver: "postgres",
// 		},
// 		map[string]string{
// 			EnvVarKey_Url: "mariadb://env_host:3306/env_segment1/env_segment2?env_arg1=env_val1&env_arg2=env_val2",
// 		},
// 	)

// 	assert.Equal(t, DbDriver_Postgres, context.UrlParts().Driver)
// }