package policy

import (
	"fmt"
	"testing"

	"github.com/seaweedfs/seaweedfs/weed/pb"
	"github.com/stretchr/testify/require"
)

// TestShellServiceAccountLifecycle exercises s3.serviceaccount.* commands end-to-end.
func TestShellServiceAccountLifecycle(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}
	cluster, err := startMiniCluster(t)
	require.NoError(t, err)
	defer cluster.Stop()

	const weedCmd = "weed"
	master := string(pb.NewServerAddress("127.0.0.1", cluster.masterPort, cluster.masterGrpcPort))
	filer := string(pb.NewServerAddress("127.0.0.1", cluster.filerPort, cluster.filerGrpcPort))

	userName := uniqueName("sauser")
	execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.user.create -name %s", userName))
	defer execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.user.delete -name %s", userName))

	var saID string

	t.Run("CreateAndList", func(t *testing.T) {
		description := "integration-test-sa"
		out := execShell(t, weedCmd, master, filer,
			fmt.Sprintf("s3.serviceaccount.create -user %s -description %s", userName, description))
		requireContains(t, out, "Created service account", "serviceaccount.create")
		requireContains(t, out, "Access Key:", "serviceaccount.create credentials")
		requireContains(t, out, "Secret Key:", "serviceaccount.create credentials")

		out = execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.serviceaccount.list -user %s", userName))
		requireContains(t, out, userName, "serviceaccount.list parent column")
		saID = extractServiceAccountID(t, out, userName)
	})

	t.Run("Show", func(t *testing.T) {
		if saID == "" {
			t.Skip("no saID extracted")
		}
		out := execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.serviceaccount.show -id %s", saID))
		requireContains(t, out, saID, "show contains id")
		requireContains(t, out, userName, "show contains parent")
		requireContains(t, out, "enabled", "show contains status")
	})

	t.Run("CreateWithActions", func(t *testing.T) {
		out := execShell(t, weedCmd, master, filer,
			fmt.Sprintf("s3.serviceaccount.create -user %s -actions Read,List -expiry 24h", userName))
		requireContains(t, out, "Access Key:", "serviceaccount.create with options")

		out = execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.serviceaccount.list -user %s", userName))
		// Should now have at least 2 service accounts — count lines that start with parent in field[1]
		count := 0
		for _, line := range splitLines(out) {
			fields := fieldsOf(line)
			if len(fields) >= 2 && fields[1] == userName {
				count++
			}
		}
		if count < 2 {
			t.Fatalf("expected at least 2 service accounts for %s, got %d\n%s", userName, count, out)
		}
	})

	t.Run("Delete", func(t *testing.T) {
		if saID == "" {
			t.Skip("no saID extracted")
		}
		execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.serviceaccount.delete -id %s", saID))
		out := execShell(t, weedCmd, master, filer, fmt.Sprintf("s3.serviceaccount.list -user %s", userName))
		requireNotContains(t, out, saID, "deleted sa removed from list")
	})
}
