package userservice_test

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	openapi "github.com/1backend/1backend/clients/go"
	sdk "github.com/1backend/1backend/sdk/go"
	"github.com/1backend/1backend/sdk/go/client"
	"github.com/1backend/1backend/sdk/go/test"
)

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

	server, err := test.StartService(test.Options{
		Test: true,
	})
	require.NoError(t, err)
	defer server.Cleanup(t)

	clientFactory := client.NewApiClientFactory(server.Url)

	ctx := context.Background()

	t.Run("non-admins cannot create users", func(t *testing.T) {
		_, _, err = clientFactory.Client().UserSvcAPI.CreateUser(ctx).Body(
			openapi.UserSvcCreateUserRequest{
				User: &openapi.UserSvcUserInput{
					Slug: "test-slug-1",
					Name: openapi.PtrString("Test Name"),
				},
			},
		).Execute()
		require.Error(t, err)
	})

	adminClient, _, err := test.AdminClient(clientFactory, sdk.DefaultTestAppHost)
	require.NoError(t, err)

	t.Run("admins can create users", func(t *testing.T) {
		_, httpRsp, err := adminClient.UserSvcAPI.CreateUser(ctx).Body(
			openapi.UserSvcCreateUserRequest{
				AppHost: openapi.PtrString(sdk.DefaultTestAppHost),
				User: &openapi.UserSvcUserInput{
					Slug: "test-slug-1",
					Name: openapi.PtrString("Test Name"),
				},
			},
		).Execute()
		require.NoError(t, err, httpRsp)
	})

	t.Run("slug is taken", func(t *testing.T) {
		_, _, err = adminClient.UserSvcAPI.CreateUser(ctx).Body(
			openapi.UserSvcCreateUserRequest{
				User: &openapi.UserSvcUserInput{
					Slug: "test-slug-1",
					Name: openapi.PtrString("Test Name"),
				},
			},
		).Execute()
		require.Error(t, err)
	})
}

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

	server, err := test.StartService(test.Options{
		Test:                true,
		TokenAutoRefreshOff: true,
		TokenExpiration:     1 * time.Second,
	})
	require.NoError(t, err)
	defer server.Cleanup(t)

	clientFactory := client.NewApiClientFactory(server.Url)

	adminClient, _, err := test.AdminClient(clientFactory, sdk.DefaultTestAppHost)
	require.NoError(t, err)

	ctx := context.Background()

	time.Sleep(1 * time.Second)

	t.Run("admins cannot create users with expired token", func(t *testing.T) {
		_, httpRsp, err := adminClient.UserSvcAPI.CreateUser(ctx).Body(
			openapi.UserSvcCreateUserRequest{
				User: &openapi.UserSvcUserInput{
					Slug: "test-slug-1",
					Name: openapi.PtrString("Test Name"),
				},
			},
		).Execute()

		require.Error(t, err, httpRsp)
		require.Equal(t, 401, httpRsp.StatusCode, httpRsp)
	})
}

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

	server, err := test.StartService(test.Options{
		Test:            true,
		TokenExpiration: time.Second,
	})
	require.NoError(t, err)
	defer server.Cleanup(t)

	clientFactory := client.NewApiClientFactory(server.Url)

	adminClient, _, err := test.AdminClient(clientFactory, sdk.DefaultTestAppHost)
	require.NoError(t, err)

	ctx := context.Background()

	time.Sleep(1 * time.Second)

	t.Run("admins can create users", func(t *testing.T) {
		_, httpRsp, err := adminClient.UserSvcAPI.CreateUser(ctx).Body(
			openapi.UserSvcCreateUserRequest{
				AppHost: openapi.PtrString(sdk.DefaultTestAppHost),
				User: &openapi.UserSvcUserInput{
					Slug: "test-slug-1",
					Name: openapi.PtrString("Test Name"),
				},
			},
		).Execute()

		require.NoError(t, err, httpRsp)
	})
}
