package arrange

import (
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"testing"

	"github.com/nexuscrm/tests/contract/internal/providerbootstrap"
	uiclient "github.com/nexuscrm/tests/contract/ui_api/client"
	"github.com/stretchr/testify/require"
)

var ensureLocalStandardObjectsOnce sync.Once

func EnsureLocalStandardObjects(t testing.TB) {
	t.Helper()

	cfg := uiclient.LoadConfigForTest(t)
	if cfg.TargetName != "local" {
		return
	}

	ensureLocalStandardObjectsOnce.Do(func() {
		lockPath := filepath.Join(os.TempDir(), "nexuscrm-ui-api-local-bootstrap.lock")
		lockFile, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0600)
		require.NoError(t, err)
		defer lockFile.Close()

		require.NoError(t, syscall.Flock(int(lockFile.Fd()), syscall.LOCK_EX))
		defer func() {
			_ = syscall.Flock(int(lockFile.Fd()), syscall.LOCK_UN)
		}()

		scriptPath, err := providerbootstrap.BaselineScriptPath()
		require.NoError(t, err)

		cmd := exec.Command("bash", scriptPath)
		cmd.Env = append(cmd.Environ(),
			"LOCAL_BACKEND_BASE_URL="+cfg.RootBaseURL,
			"LOCAL_BACKEND_TOKEN_URL="+cfg.TokenURL,
			"REST_API_API_VERSION="+cfg.APIVersion,
			"LOCAL_BACKEND_CLIENT_ID="+cfg.ClientID,
			"LOCAL_BACKEND_CLIENT_SECRET="+cfg.ClientSecret,
		)

		output, err := cmd.CombinedOutput()
		require.NoError(t, err, "initialize local standard objects: %s", strings.TrimSpace(string(output)))
	})
}

func FirstRecordID(t testing.TB, client *uiclient.Client, objectName string) string {
	t.Helper()

	resp, err := client.Get("/query?q=" + url.QueryEscape("SELECT Id FROM "+objectName+" LIMIT 1"))
	require.NoError(t, err)
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		t.Fatalf("query status %d: %s", resp.StatusCode, string(body))
	}

	var payload struct {
		Records []map[string]any `json:"records"`
	}
	require.NoError(t, json.NewDecoder(resp.Body).Decode(&payload))
	require.NotEmpty(t, payload.Records, "no %s records returned", objectName)

	id, _ := payload.Records[0]["Id"].(string)
	if strings.TrimSpace(id) == "" {
		t.Fatalf("missing Id in %s query response", objectName)
	}
	return id
}
