package config_test

import (
	"fmt"
	"os"
	"testing"

	"github.com/spf13/cobra"
	"github.com/stretchr/testify/require"

	"git.cw.tr/mukan-network/mukan-sdk/client"
	"git.cw.tr/mukan-network/mukan-sdk/client/config"
	"git.cw.tr/mukan-network/mukan-sdk/client/flags"
	"git.cw.tr/mukan-network/mukan-sdk/codec"
	codectypes "git.cw.tr/mukan-network/mukan-sdk/codec/types"
	clitestutil "git.cw.tr/mukan-network/mukan-sdk/testutil/cli"
)

const (
	chainID   = "test-chain"
	nodeEnv   = "CONFIG_TEST_NODE"
	testNode1 = "http://localhost:1"
	testNode2 = "http://localhost:2"
)

// initClientContext initiates client Context for tests
func initClientContext(t *testing.T, envVar string) (client.Context, func()) {
	t.Helper()
	home := t.TempDir()
	clientCtx := client.Context{}.
		WithHomeDir(home).
		WithViper("").
		WithCodec(codec.NewProtoCodec(codectypes.NewInterfaceRegistry())).
		WithChainID(chainID)

	if envVar != "" {
		require.NoError(t, os.Setenv(nodeEnv, envVar))
	}

	clientCtx, err := config.ReadFromClientConfig(clientCtx)
	require.NoError(t, err)
	require.Equal(t, clientCtx.ChainID, chainID)

	return clientCtx, func() {
		_ = os.RemoveAll(home)
		_ = os.Unsetenv(nodeEnv)
	}
}

func TestConfigCmdEnvFlag(t *testing.T) {
	tt := []struct {
		name    string
		envVar  string
		args    []string
		expNode string
	}{
		{"env var is set with no flag", testNode1, []string{}, testNode1},
		{"env var is set with a flag", testNode1, []string{fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2},
		{"env var is not set with no flag", "", []string{}, "tcp://localhost:26657"},
		{"env var is not set with a flag", "", []string{fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2},
	}

	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			testCmd := &cobra.Command{
				Use: "test",
				RunE: func(cmd *cobra.Command, args []string) error {
					clientCtx, err := client.GetClientQueryContext(cmd)
					if err != nil {
						return err
					}

					return fmt.Errorf("%s", clientCtx.NodeURI)
				},
			}
			flags.AddQueryFlagsToCmd(testCmd)

			clientCtx, cleanup := initClientContext(t, tc.envVar)
			defer func() {
				cleanup()
			}()
			/*
				env var is set with a flag

				NODE=http://localhost:1 test-cmd --node http://localhost:2
				Prints "http://localhost:2"

				It prints http://localhost:2 cause a flag has the higher priority than env variable.
			*/

			_, err := clitestutil.ExecTestCLICmd(clientCtx, testCmd, tc.args)
			require.Error(t, err)
			require.Contains(t, err.Error(), tc.expNode)
		})
	}
}
