package service

import (
	"context"
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/pkgv2/clusterproxy/tidbcloud"
	"github.com/tidbcloud/serverless-service/internal/config"
)

func TestNewNewArchTiCDCClientBuildsBaseURLFromClusterProxyURL(t *testing.T) {
	setConfigForTest(t, &config.CentralConfig{
		ServerConfig: config.ServerConfig{Stage: config.StageDev},
	})

	client, err := newNewArchTiCDCClient(context.Background(), "http://cluster-proxy.example.com/some/path")
	require.NoError(t, err)
	require.Equal(t,
		"http://cluster-proxy.example.com/proxy/namespace/tidb-serverless/cluster/serverless-cluster",
		client.baseURL,
	)
	require.Equal(t, 45*time.Second, client.httpClient.Timeout)
}

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

	var gotMethod string
	var gotContentType string
	var gotBody []byte
	var readErr error
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		gotMethod = r.Method
		gotContentType = r.Header.Get("Content-Type")
		gotBody, readErr = io.ReadAll(r.Body)
		w.WriteHeader(http.StatusOK)
	}))
	defer srv.Close()

	client := &newArchTiCDCClient{
		baseURL:    srv.URL,
		httpClient: srv.Client(),
		authCfg:    tidbcloud.ProxyConfig{DevMode: true},
	}

	err := client.request(context.Background(), http.MethodGet, srv.URL, nil, nil)
	require.NoError(t, err)
	require.NoError(t, readErr)
	require.Equal(t, http.MethodGet, gotMethod)
	require.Empty(t, gotContentType)
	require.Empty(t, gotBody)
}

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

	var gotContentType string
	var got map[string]string
	var readErr error
	var unmarshalErr error
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		gotContentType = r.Header.Get("Content-Type")
		body, err := io.ReadAll(r.Body)
		readErr = err
		unmarshalErr = json.Unmarshal(body, &got)
		w.WriteHeader(http.StatusOK)
	}))
	defer srv.Close()

	client := &newArchTiCDCClient{
		baseURL:    srv.URL,
		httpClient: srv.Client(),
		authCfg:    tidbcloud.ProxyConfig{DevMode: true},
	}

	err := client.request(context.Background(), http.MethodPost, srv.URL, map[string]string{"k": "v"}, nil)
	require.NoError(t, err)
	require.NoError(t, readErr)
	require.NoError(t, unmarshalErr)
	require.Equal(t, "application/json", gotContentType)
	require.Equal(t, map[string]string{"k": "v"}, got)
}
