//go:build !integration

package update

import (
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/mock/gomock"

	gitlab "gitlab.com/gitlab-org/api/client-go/v2"
	gitlabtesting "gitlab.com/gitlab-org/api/client-go/v2/testing"

	"gitlab.com/gitlab-org/cli/internal/api"
	"gitlab.com/gitlab-org/cli/internal/testing/cmdtest"
)

func TestUpdate(t *testing.T) {
	t.Parallel()

	tc := gitlabtesting.NewTestClient(t)

	exec := cmdtest.SetupCmdForTest(
		t,
		NewCmd,
		false,
		cmdtest.WithApiClient(cmdtest.NewTestApiClient(t, nil, "", "", api.WithGitLabClient(tc.Client))),
	)

	fixedTime := time.Date(2025, 1, 15, 10, 30, 0, 0, time.UTC)
	tc.MockRunnerControllers.EXPECT().
		UpdateRunnerController(int64(42), gomock.Any(), gomock.Any()).
		Return(&gitlab.RunnerController{
			ID:          42,
			Description: "Updated Controller",
			State:       gitlab.RunnerControllerStateEnabled,
			CreatedAt:   &fixedTime,
			UpdatedAt:   &fixedTime,
		}, nil, nil)

	out, err := exec("42 --description 'Updated Controller' --state enabled")
	require.NoError(t, err)
	assert.Equal(t, "Updated runner controller 42\n", out.OutBuf.String())
}

func TestUpdateJSON(t *testing.T) {
	t.Parallel()

	tc := gitlabtesting.NewTestClient(t)

	exec := cmdtest.SetupCmdForTest(
		t,
		NewCmd,
		false,
		cmdtest.WithApiClient(cmdtest.NewTestApiClient(t, nil, "", "", api.WithGitLabClient(tc.Client))),
	)

	fixedTime := time.Date(2025, 1, 15, 10, 30, 0, 0, time.UTC)
	tc.MockRunnerControllers.EXPECT().
		UpdateRunnerController(int64(42), gomock.Any(), gomock.Any()).
		Return(&gitlab.RunnerController{
			ID:          42,
			Description: "Updated Controller",
			State:       gitlab.RunnerControllerStateEnabled,
			CreatedAt:   &fixedTime,
			UpdatedAt:   &fixedTime,
		}, nil, nil)

	out, err := exec("42 --description 'Updated Controller' --output json")
	require.NoError(t, err)
	assert.Contains(t, out.OutBuf.String(), `"id":42`)
}

func TestUpdateError(t *testing.T) {
	t.Parallel()

	tc := gitlabtesting.NewTestClient(t)

	exec := cmdtest.SetupCmdForTest(
		t,
		NewCmd,
		false,
		cmdtest.WithApiClient(cmdtest.NewTestApiClient(t, nil, "", "", api.WithGitLabClient(tc.Client))),
	)

	tc.MockRunnerControllers.EXPECT().
		UpdateRunnerController(int64(42), gomock.Any(), gomock.Any()).
		Return(nil, nil, errors.New("API error"))

	_, err := exec("42 --description 'Test'")
	require.Error(t, err)
	assert.Contains(t, err.Error(), "API error")
}

func TestUpdateMissingFlags(t *testing.T) {
	t.Parallel()

	tc := gitlabtesting.NewTestClient(t)

	exec := cmdtest.SetupCmdForTest(
		t,
		NewCmd,
		false,
		cmdtest.WithApiClient(cmdtest.NewTestApiClient(t, nil, "", "", api.WithGitLabClient(tc.Client))),
	)

	_, err := exec("42")
	require.Error(t, err)
	assert.Contains(t, err.Error(), "at least one of the flags")
}

func TestUpdateInvalidID(t *testing.T) {
	t.Parallel()

	tc := gitlabtesting.NewTestClient(t)

	exec := cmdtest.SetupCmdForTest(
		t,
		NewCmd,
		false,
		cmdtest.WithApiClient(cmdtest.NewTestApiClient(t, nil, "", "", api.WithGitLabClient(tc.Client))),
	)

	_, err := exec("invalid --description 'Test'")
	require.Error(t, err)
	assert.Contains(t, err.Error(), "invalid")
}
