package pilgrim_conf_test

import (
	"flag"
	"fmt"
	"testing"

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

func Test_CliContext_Url(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Url() },
		pilgrim_conf.Flag_Url,
		"driver://localhost:3306",
	)
}

func Test_CliContext_Driver(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (pilgrim_conf.DbDriver, bool) { return cli.Driver() },
		pilgrim_conf.Flag_Driver,
		"driver",
	)
}

func Test_CliContext_Username(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Username() },
		pilgrim_conf.Flag_Username,
		"username",
	)
}

func Test_CliContext_Password(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Password() },
		pilgrim_conf.Flag_Password,
		"password",
	)
}

func Test_CliContext_Host(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Host() },
		pilgrim_conf.Flag_Host,
		"localhost",
	)
}

func Test_CliContext_Port(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Port() },
		pilgrim_conf.Flag_Port,
		"3306",
	)
}

func Test_CliContext_Segments(t *testing.T) {
	expectedValue := []string{
		"segment1", "segment2", "segment3",
	}

	flag.Set(pilgrim_conf.Flag_Segments, "segment1/segment2/segment3")

	value, _ := pilgrim_conf.CliContext().Segments()

	assert.Equal(t, expectedValue, value)
}

func Test_CliContext_Args(t *testing.T) {
	expectedValue := map[string]string{
		"arg1": "val1",
		"arg2": "val2",
		"arg3": "val3",
	}

	flag.Set(pilgrim_conf.Flag_Args, "arg1=val1&arg2=val2&arg3=val3")

	value, _ := pilgrim_conf.CliContext().Args()

	assert.Equal(t, expectedValue, value)
}

func Test_CliContext_Directory(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Directory() },
		pilgrim_conf.Flag_Directory,
		"./custom-migrations",
	)
}

func Test_CliContext_Script(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.Script() },
		pilgrim_conf.Flag_Script,
		"2024-10-13/1_SomeScript.sql",
	)
}

func Test_CliContext_MigrationTable(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) { return cli.MigrationTable() },
		pilgrim_conf.Flag_Table,
		"CustomMigrationsTable",
	)
}

func Test_CliContext_MigrationTableSchema(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (string, bool) {
			return pilgrim_conf.CliContext().MigrationTableSchema()
		},
		pilgrim_conf.Flag_Schema,
		"public",
	)
}

func Test_CliContext_Up(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (bool, bool) { return cli.IsUp() },
		pilgrim_conf.Flag_Up,
		true,
	)
}

func Test_CliContext_Down(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (bool, bool) { return cli.IsDown() },
		pilgrim_conf.Flag_Down,
		true,
	)
}
func Test_CliContext_StrictOrdering(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (bool, bool) {
			return pilgrim_conf.CliContext().IsStrictOrderingEnabled()
		},
		pilgrim_conf.Flag_StrictOrdering,
		true,
	)
}

func Test_CliContext_DisableChecksumValidation(t *testing.T) {
	expectedValue := false

	flag.Set(pilgrim_conf.Flag_DisableChecksumValidation, "true")

	value, _ := pilgrim_conf.CliContext().IsChecksumValidationEnabled()

	assert.Equal(t, expectedValue, value)
}

func Test_CliContext_ValidateChecksums(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (bool, bool) {
			return cli.IsValidatingChecksums()
		},
		pilgrim_conf.Flag_ValidateChecksums,
		true,
	)
}

func Test_CliContext_ValidateMigrationOrder(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (bool, bool) {
			return cli.IsValidatingMigrationOrder()
		},
		pilgrim_conf.Flag_ValidateMigrationOrder,
		true,
	)
}

func Test_CliContext_ValidateLatest(t *testing.T) {
	test_cliValue(
		t,
		func(cli pilgrim_conf.CliFlagRetriever) (bool, bool) { return cli.IsValidatingLatest() },
		pilgrim_conf.Flag_ValidateLatest,
		true,
	)
}

func test_cliValue[T string | pilgrim_conf.DbDriver | bool](t *testing.T, cliVal func(cli pilgrim_conf.CliFlagRetriever) (value T, isProvided bool), flagName string, expectedVal T) {
	cli := pilgrim_conf.CliContext()

	flag.Set(flagName, fmt.Sprintf("%v", expectedVal))

	cli.ParseFlags()

	value, _ := cliVal(cli)

	assert.Equal(t, expectedVal, value)
}