package asset

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

	"github.com/stretchr/testify/require"
)

func TestPostAgentsBatchAccessPostsAgentIDAndOmitsEmptyTemplateLocale(t *testing.T) {
	var capturedWorkspace, capturedRouteWorkspace string
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "/api/v1/workspaces/ws_1/memory/agents/access:batch", r.URL.Path)
		require.Equal(t, "Bearer user-token", r.Header.Get("Authorization"))
		capturedWorkspace = r.Header.Get("X-Workspace-Id")
		capturedRouteWorkspace = r.Header.Get("X-AgentTeam-Route-Workspace-Id")
		var req batchRequest
		require.NoError(t, json.NewDecoder(r.Body).Decode(&req))
		require.Equal(t, []string{"agt_1"}, req.AgentIDs)
		require.Empty(t, req.TemplateLocale)
		_ = json.NewEncoder(w).Encode(map[string]any{"ok": true})
	}))
	defer ts.Close()

	var out struct {
		OK bool `json:"ok"`
	}
	endpoint, err := PostAgentsBatchAccess(context.Background(), nil, ConnectionInfo{ServerURL: ts.URL + "/", UserToken: " user-token ", WorkspaceID: "ws_1"}, "/api/v1/memory/agents/access:batch", []string{" agt_1 "}, &out)
	require.NoError(t, err)
	require.Equal(t, ts.URL+"/api/v1/workspaces/ws_1/memory/agents/access:batch", endpoint)
	require.Equal(t, "ws_1", capturedWorkspace)
	require.Equal(t, capturedWorkspace, capturedRouteWorkspace)
	require.True(t, out.OK)
}

func TestPostAgentsBatchAccessRefreshesTokenOnceAfterUnauthorized(t *testing.T) {
	var calls int
	var seen []string
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		calls++
		seen = append(seen, r.Header.Get("Authorization"))
		if calls == 1 {
			w.WriteHeader(http.StatusUnauthorized)
			return
		}
		_ = json.NewEncoder(w).Encode(map[string]any{"ok": true})
	}))
	defer ts.Close()
	var out struct {
		OK bool `json:"ok"`
	}
	refreshes := 0
	endpoint, err := PostAgentsBatchAccess(context.Background(), nil, ConnectionInfo{
		ServerURL: ts.URL, UserToken: "stale", WorkspaceID: "ws_1",
		RefreshUserToken: func(context.Context, string) (string, error) {
			refreshes++
			return "fresh", nil
		},
	}, "/api/v1/memory/agents/access:batch", []string{"agt_1"}, &out)
	require.NoError(t, err)
	require.True(t, out.OK)
	require.Equal(t, ts.URL+"/api/v1/workspaces/ws_1/memory/agents/access:batch", endpoint)
	require.Equal(t, 1, refreshes)
	require.Equal(t, []string{"Bearer stale", "Bearer fresh"}, seen)
}

func TestPostAgentsBatchAccessDoesNotAgentTeamWhenRefreshedTokenIsUnauthorized(t *testing.T) {
	var calls int
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		calls++
		w.WriteHeader(http.StatusUnauthorized)
	}))
	defer ts.Close()
	refreshes := 0
	var out struct {
		OK bool `json:"ok"`
	}
	_, err := PostAgentsBatchAccess(context.Background(), nil, ConnectionInfo{
		ServerURL: ts.URL, UserToken: "stale", WorkspaceID: "ws_1",
		RefreshUserToken: func(context.Context, string) (string, error) {
			refreshes++
			return "fresh", nil
		},
	}, "/api/v1/memory/agents/access:batch", []string{"agt_1"}, &out)
	require.EqualError(t, err, "assetprovider: batch access: status 401")
	require.Equal(t, 1, refreshes)
	require.Equal(t, 2, calls)
}

func TestPostAgentsBatchAccessRequiresWorkspaceID(t *testing.T) {
	var out struct {
		OK bool `json:"ok"`
	}
	_, err := PostAgentsBatchAccess(context.Background(), nil, ConnectionInfo{
		ServerURL: "https://agentteam.example.com",
		UserToken: "user-token",
	}, "/api/v1/memory/agents/access:batch", []string{"agt_1"}, &out)

	require.ErrorContains(t, err, "server URL, token, or workspace")
}

func TestPostAgentsBatchAccessPostsTemplateLocaleWhenProvided(t *testing.T) {
	var captured batchRequest
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "/api/v1/workspaces/ws_1/skills/agents/access:batch", r.URL.Path)
		require.NoError(t, json.NewDecoder(r.Body).Decode(&captured))
		_ = json.NewEncoder(w).Encode(map[string]any{"ok": true})
	}))
	defer ts.Close()

	var out struct {
		OK bool `json:"ok"`
	}
	_, err := PostAgentsBatchAccess(context.Background(), nil, ConnectionInfo{
		ServerURL:      ts.URL,
		UserToken:      "user-token",
		WorkspaceID:    "ws_1",
		TemplateLocale: " zh-CN ",
	}, "/api/v1/skills/agents/access:batch", []string{"agt_1"}, &out)

	require.NoError(t, err)
	require.Equal(t, []string{"agt_1"}, captured.AgentIDs)
	require.Equal(t, "zh-CN", captured.TemplateLocale)
	require.True(t, out.OK)
}

func TestComposeCloneURLRequiresRepoFullName(t *testing.T) {
	require.Equal(t, "https://agentteam.example.com/api/v1/workspaces/wsp_1/ags/owner/repo.git", ComposeCloneURL("https://agentteam.example.com/", "wsp_1", " /owner/repo/ "))
	require.Equal(t, "", ComposeCloneURL("https://agentteam.example.com", "", "owner/repo"))
	require.Equal(t, "", ComposeCloneURL("https://agentteam.example.com", "wsp_1", ""))
	require.Equal(t, "", ComposeCloneURL("", "wsp_1", "owner/repo"))
}
