package tenant

import (
	"context"
	"net/http"
	"time"

	"github.com/go-errors/errors"
	"github.com/supabase/cli/internal/utils"
	"github.com/supabase/cli/pkg/api"
	"github.com/supabase/cli/pkg/fetcher"
)

var (
	ErrAuthToken  = errors.New("Authorization failed for the access token and project ref pair")
	errMissingKey = errors.New("Anon key not found.")
)

type ApiKey struct {
	Anon        string
	ServiceRole string
}

func (a ApiKey) IsEmpty() bool {
	return len(a.Anon) == 0 && len(a.ServiceRole) == 0
}

func NewApiKey(resp []api.ApiKeyResponse) ApiKey {
	var result ApiKey
	for _, key := range resp {
		if key.Name == "anon" {
			result.Anon = key.ApiKey
		}
		if key.Name == "service_role" {
			result.ServiceRole = key.ApiKey
		}
	}
	return result
}

func GetApiKeys(ctx context.Context, projectRef string) (ApiKey, error) {
	resp, err := utils.GetSupabase().V1GetProjectApiKeysWithResponse(ctx, projectRef, &api.V1GetProjectApiKeysParams{})
	if err != nil {
		return ApiKey{}, errors.Errorf("failed to get api keys: %w", err)
	}
	if resp.JSON200 == nil {
		return ApiKey{}, errors.Errorf("%w: %s", ErrAuthToken, string(resp.Body))
	}
	keys := NewApiKey(*resp.JSON200)
	if keys.IsEmpty() {
		return ApiKey{}, errors.New(errMissingKey)
	}
	return keys, nil
}

type TenantAPI struct {
	*fetcher.Fetcher
}

func NewTenantAPI(ctx context.Context, projectRef, anonKey string) TenantAPI {
	server := "https://" + utils.GetSupabaseHost(projectRef)
	client := &http.Client{
		Timeout: 10 * time.Second,
	}
	header := func(req *http.Request) {
		req.Header.Add("apikey", anonKey)
	}
	api := TenantAPI{Fetcher: fetcher.NewFetcher(
		server,
		fetcher.WithHTTPClient(client),
		fetcher.WithRequestEditor(header),
		fetcher.WithUserAgent("SupabaseCLI/"+utils.Version),
		fetcher.WithExpectedStatus(http.StatusOK),
	)}
	return api
}
