package cmd

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/daemon"
	"github.com/tidbcloud/AgentTeam/desktop/internal/operator"
)

func TestParseConnectURL(t *testing.T) {
	token, serverURL, err := parseConnectURL("agentteam://connect?token=abc&origin=https%3A%2F%2Fagentteam.example.com")
	require.NoError(t, err)
	require.Equal(t, "abc", token)
	require.Equal(t, "https://agentteam.example.com", serverURL)
}

func TestExchangeMachineConnectToken(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "/api/v1/machine-connect-exchanges", r.URL.Path)
		w.Header().Set("Content-Type", "application/json")
		_, _ = w.Write([]byte(`{"machineId":"mac_1","apiKey":"key_1","serverUrl":"https://agentteam.example.com","workspaceId":"wsp_1"}`))
	}))
	defer server.Close()

	result, err := exchangeMachineConnectToken(server.URL, "tok_1")
	require.NoError(t, err)
	require.Equal(t, "mac_1", result.MachineID)
	require.Equal(t, "key_1", result.APIKey)
	require.Equal(t, "https://agentteam.example.com", result.ServerURL)
	require.Equal(t, "wsp_1", result.WorkspaceID)
}

func TestRunConnectStartsHeadlessDaemon(t *testing.T) {
	originalGetOperator := getOperator
	originalDaemonStatus := daemonStatus
	originalRunDaemonForeground := runDaemonForeground
	originalConnectOpts := connectOpts
	t.Cleanup(func() {
		getOperator = originalGetOperator
		daemonStatus = originalDaemonStatus
		runDaemonForeground = originalRunDaemonForeground
		connectOpts = originalConnectOpts
	})
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		_, _ = w.Write([]byte(`{"machineId":"mac_1","apiKey":"key_1","serverUrl":"https://agentteam.example.com","workspaceId":"wsp_1"}`))
	}))
	defer server.Close()

	fakeChannels := &fakeChannelOperator{}
	getOperator = func() (operator.Operator, error) {
		return fakeOperator{servers: fakeChannels}, nil
	}
	daemonStatus = func() *daemon.Status {
		return &daemon.Status{Running: false}
	}
	runDaemonForeground = func() error {
		return nil
	}

	connectOpts.token = "tok_1"
	connectOpts.serverURL = server.URL

	require.NoError(t, runConnect(connectCmd, nil))
	require.Len(t, fakeChannels.servers, 1)
	cfg := configToMap(fakeChannels.servers[0].Config)
	require.Equal(t, "wsp_1", cfg["workspace_id"])
}

func TestRunConnectLeavesHealthyDaemonRunning(t *testing.T) {
	originalGetOperator := getOperator
	originalDaemonStatus := daemonStatus
	originalRunDaemonForeground := runDaemonForeground
	originalConnectOpts := connectOpts
	t.Cleanup(func() {
		getOperator = originalGetOperator
		daemonStatus = originalDaemonStatus
		runDaemonForeground = originalRunDaemonForeground
		connectOpts = originalConnectOpts
	})

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		_, _ = w.Write([]byte(`{"machineId":"mac_1","apiKey":"key_1","serverUrl":"https://agentteam.example.com","workspaceId":"wsp_1"}`))
	}))
	defer server.Close()

	getOperator = func() (operator.Operator, error) {
		return fakeOperator{servers: &fakeChannelOperator{}}, nil
	}
	daemonStatus = func() *daemon.Status {
		return &daemon.Status{Running: true, Healthy: true, PID: 321}
	}

	runDaemonForeground = func() error {
		t.Fatal("did not expect daemon restart when it is already healthy")
		return nil
	}

	connectOpts.token = "tok_1"
	connectOpts.serverURL = server.URL

	require.NoError(t, runConnect(connectCmd, nil))
}
