package mcp

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"sync/atomic"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/wire/apiclient"
)

func TestResolveFreshnessTargetKeyUsesSharedCache(t *testing.T) {
	var resolveCalls atomic.Int32
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, http.MethodPost, r.Method)
		resolveCalls.Add(1)
		_, _ = io.WriteString(w, `{"scopeId":"chn_1","targetKey":"target_1"}`)
	}))
	t.Cleanup(server.Close)
	client := &apiclient.Client{
		ServerURL: server.URL, RouteWorkspaceID: "wsp_1",
		AgentID: "agt_1", AuthToken: "token", HTTPClient: server.Client(),
		TargetResolver: apiclient.NewTargetResolver(),
	}
	handler := &mcpHandler{}

	for range 2 {
		targetKey, err := handler.resolveFreshnessTargetKey(context.Background(), client, "#ops")
		require.NoError(t, err)
		require.Equal(t, "target_1", targetKey)
	}
	require.Equal(t, int32(1), resolveCalls.Load())
}

func TestUploadFileViaAPIInvalidatesStaleScopeWithoutReplay(t *testing.T) {
	var resolveCalls atomic.Int32
	var uploadCalls atomic.Int32
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		switch {
		case r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/resolve-channel"):
			scopeID := fmt.Sprintf("chn_%d", resolveCalls.Add(1))
			_, _ = fmt.Fprintf(w, `{"scopeId":%q}`, scopeID)
		case r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/upload"):
			call := uploadCalls.Add(1)
			require.NoError(t, r.ParseMultipartForm(1<<20))
			require.Equal(t, fmt.Sprintf("chn_%d", call), r.FormValue("scopeId"))
			if call == 1 {
				w.WriteHeader(http.StatusForbidden)
				_, _ = io.WriteString(w, `{"error":"scope denied"}`)
				return
			}
			_, _ = io.WriteString(w, `{"id":"att_1"}`)
		default:
			t.Fatalf("unexpected request %s %s", r.Method, r.URL.Path)
		}
	}))
	t.Cleanup(server.Close)
	client := &apiclient.Client{
		ServerURL: server.URL, RouteWorkspaceID: "wsp_1",
		AgentID: "agt_1", AuthToken: "token", HTTPClient: server.Client(),
		TargetResolver: apiclient.NewTargetResolver(),
	}
	filePath := filepath.Join(t.TempDir(), "note.txt")
	require.NoError(t, os.WriteFile(filePath, []byte("hello"), 0o600))
	handler := &mcpHandler{}

	_, err := handler.uploadFileViaAPI(context.Background(), client, "#ops", filePath)
	require.Error(t, err)
	require.Equal(t, int32(1), uploadCalls.Load(), "failed upload must not be replayed")

	attachmentID, err := handler.uploadFileViaAPI(context.Background(), client, "#ops", filePath)
	require.NoError(t, err)
	require.Equal(t, "att_1", attachmentID)
	require.Equal(t, int32(2), resolveCalls.Load())
	require.Equal(t, int32(2), uploadCalls.Load())
}
