package k8s_test

import (
	"encoding/json"
	"os"
	"path"
	"testing"

	"github.com/scaleway/scaleway-cli/v2/core"
	"github.com/scaleway/scaleway-cli/v2/internal/namespaces/k8s/v1"
	"github.com/scaleway/scaleway-sdk-go/scw"
	"github.com/stretchr/testify/assert"
)

const (
	p1Secret  = "00000000-0000-0000-0000-111111111111"
	p2Secret  = "00000000-0000-0000-0000-222222222222"
	p3Secret  = "00000000-0000-0000-0000-333333333333"
	envSecret = "66666666-6666-6666-6666-666666666666"
)

func Test_ExecCredential(t *testing.T) {
	////
	// Simple expect to return current secret_key
	////
	t.Run("simple", core.Test(&core.TestConfig{
		Commands:   k8s.GetCommands(),
		TmpHomeDir: true,
		BeforeFunc: beforeFuncCreateFullConfig(),
		Cmd:        "scw k8s exec-credential",
		OverrideEnv: map[string]string{
			scw.ScwAccessKeyEnv: "", // Ignore keys in test env
			scw.ScwSecretKeyEnv: "", // Ignore keys in test env
		},
		Check: core.TestCheckCombine(
			core.TestCheckExitCode(0),
			core.TestCheckGolden(),
			assertTokenInResponse(p1Secret),
		),
	}))

	////
	// expect to return 66666666-6666-6666-6666-666666666666
	////
	t.Run("with scw_secret_key env", core.Test(&core.TestConfig{
		Commands:   k8s.GetCommands(),
		TmpHomeDir: true,
		BeforeFunc: beforeFuncCreateFullConfig(),
		Cmd:        "scw k8s exec-credential",
		OverrideEnv: map[string]string{
			scw.ScwSecretKeyEnv: envSecret,
		},
		Check: core.TestCheckCombine(
			core.TestCheckExitCode(0),
			core.TestCheckGolden(),
			assertTokenInResponse(envSecret),
		),
	}))

	////
	// expect to return p2 secret_key
	////
	t.Run("with profile env", core.Test(&core.TestConfig{
		Commands:   k8s.GetCommands(),
		TmpHomeDir: true,
		BeforeFunc: beforeFuncCreateFullConfig(),
		Cmd:        "scw k8s exec-credential",
		OverrideEnv: map[string]string{
			scw.ScwActiveProfileEnv: "p2",
			scw.ScwAccessKeyEnv:     "", // Ignore keys in test env
			scw.ScwSecretKeyEnv:     "", // Ignore keys in test env
		},
		Check: core.TestCheckCombine(
			core.TestCheckExitCode(0),
			core.TestCheckGolden(),
			assertTokenInResponse(p2Secret),
		),
	}))

	////
	// expect to return p3 secret_key
	////
	t.Run("with profile flag", core.Test(&core.TestConfig{
		Commands:   k8s.GetCommands(),
		TmpHomeDir: true,
		BeforeFunc: beforeFuncCreateFullConfig(),
		Cmd:        "scw --profile p3 k8s exec-credential",
		OverrideEnv: map[string]string{
			scw.ScwAccessKeyEnv: "", // Ignore keys in test env
			scw.ScwSecretKeyEnv: "", // Ignore keys in test env
		},
		Check: core.TestCheckCombine(
			core.TestCheckExitCode(0),
			core.TestCheckGolden(),
			assertTokenInResponse(p3Secret),
		),
	}))

	////
	// expect to return p3 secret_key
	////
	t.Run("with profile env and flag", core.Test(&core.TestConfig{
		Commands:   k8s.GetCommands(),
		TmpHomeDir: true,
		BeforeFunc: beforeFuncCreateFullConfig(),
		Cmd:        "scw --profile p3 k8s exec-credential",
		OverrideEnv: map[string]string{
			scw.ScwActiveProfileEnv: "p2",
			scw.ScwAccessKeyEnv:     "", // Ignore keys in test env
			scw.ScwSecretKeyEnv:     "", // Ignore keys in test env
		},
		Check: core.TestCheckCombine(
			core.TestCheckExitCode(0),
			core.TestCheckGolden(),
			assertTokenInResponse(p3Secret),
		),
	}))
}

func beforeFuncCreateConfigFile(c *scw.Config) core.BeforeFunc {
	return func(ctx *core.BeforeFuncCtx) error {
		homeDir := ctx.OverrideEnv["HOME"]
		scwDir := path.Join(homeDir, ".config", "scw")
		if err := os.MkdirAll(scwDir, 0o0755); err != nil {
			return err
		}

		scwPath := path.Join(scwDir, "config.yaml")
		if err := c.SaveTo(scwPath); err != nil {
			return err
		}

		return nil
	}
}

func beforeFuncCreateFullConfig() core.BeforeFunc {
	return beforeFuncCreateConfigFile(&scw.Config{
		Profile: scw.Profile{
			AccessKey:             new("SCWXXXXXXXXXXXXXXXXX"),
			SecretKey:             new(p1Secret),
			APIURL:                new("https://mock-api-url.com"),
			Insecure:              new(true),
			DefaultOrganizationID: new("deadbeef-dead-dead-dead-deaddeafbeef"),
			DefaultProjectID:      new("deadbeef-dead-dead-dead-deaddeafbeef"),
			DefaultRegion:         new("fr-par"),
			DefaultZone:           new("fr-par-1"),
			SendTelemetry:         new(true),
		},
		Profiles: map[string]*scw.Profile{
			"p2": {
				AccessKey:             new("SCWP2XXXXXXXXXXXXXXX"),
				SecretKey:             new(p2Secret),
				APIURL:                new("https://p2-mock-api-url.com"),
				Insecure:              new(true),
				DefaultOrganizationID: new("deadbeef-dead-dead-dead-deaddeafbeef"),
				DefaultProjectID:      new("deadbeef-dead-dead-dead-deaddeafbeef"),
				DefaultRegion:         new("fr-par"),
				DefaultZone:           new("fr-par-1"),
				SendTelemetry:         new(true),
			},
			"p3": {
				AccessKey:             new("SCWP3XXXXXXXXXXXXXXX"),
				SecretKey:             new(p3Secret),
				APIURL:                new("https://p3-mock-api-url.com"),
				Insecure:              new(true),
				DefaultOrganizationID: new("deadbeef-dead-dead-dead-deaddeafbeef"),
				DefaultProjectID:      new("deadbeef-dead-dead-dead-deaddeafbeef"),
				DefaultRegion:         new("fr-par"),
				DefaultZone:           new("fr-par-1"),
				SendTelemetry:         new(true),
			},
		},
	})
}

func assertTokenInResponse(expectedToken string) core.TestCheck {
	return func(t *testing.T, ctx *core.CheckFuncCtx) {
		t.Helper()
		res := ctx.Result.(string)
		creds := k8s.ExecCredential{}
		err := json.Unmarshal([]byte(res), &creds)
		if err != nil {
			t.Fatal(err)
		}
		assert.Equal(t, expectedToken, creds.Status.Token)
	}
}
