package task_test

import (
	"net/http"
	"testing"
	"time"

	"net/http/httptest"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/api/testkit"
)

// TestHumanCollaboratorRequestHTTPFlow drives the real collaborator-request
// HTTP endpoints end-to-end: an owner creates a task, a second Human submits a
// request to become a collaborator via POST /collaborator-requests, verifies the
// 7-day approval validity is reported separately from the collaborator expiry,
// and the requester status surface lists it as pending. This is the automated
// proxy for the manual two-Human QA.
func TestHumanCollaboratorRequestHTTPFlow(t *testing.T) {
	runtime := testkit.StartRuntime(t)
	router := gin.New()
	runtime.RegisterRoutes(router)
	server := httptest.NewServer(router)
	client := server.Client()

	owner, workspaceID, channelID := testkit.SetupTaskHTTPActor(
		t, client, server.URL, "collab-req-owner@example.com", "collab-req-owner",
	)
	requester := testkit.AcceptTaskHTTPInvite(
		t, runtime, client, server.URL, owner.User.ID, workspaceID, "collab-req-requester@example.com", "collab-req-requester",
	)

	// Owner creates a task.
	var createResp struct {
		Tasks []struct {
			TaskScopeID string `json:"taskScopeId"`
		} `json:"tasks"`
	}
	response := testkit.DoJSON(t, client, http.MethodPost, server.URL+"/api/v1/workspaces/"+workspaceID+"/channels/"+channelID+"/tasks", map[string]any{
		"tasks": []map[string]any{{"title": "collaborator request target"}},
	}, testkit.WorkspaceHeaders(owner.AccessToken, workspaceID), &createResp)
	require.Equal(t, http.StatusOK, response.StatusCode)
	require.Len(t, createResp.Tasks, 1)
	taskScopeID := createResp.Tasks[0].TaskScopeID

	// Requester submits a collaborator request with a collaborator expiry.
	var submitResp struct {
		ApprovalID string `json:"approvalId"`
		RequestID  string `json:"requestId"`
		Status     string `json:"status"`
	}
	response = testkit.DoJSON(t, client, http.MethodPost, server.URL+"/api/v1/workspaces/"+workspaceID+"/collaborator-requests", map[string]any{
		"scopeType":             "task",
		"scopeId":               taskScopeID,
		"role":                  "contributor",
		"collaboratorExpiresAt": time.Now().UTC().Add(2 * 24 * time.Hour).Format(time.RFC3339),
		"clientRequestId":       "http-cr-1",
	}, testkit.WorkspaceHeaders(requester.AccessToken, workspaceID), &submitResp)
	require.Equal(t, http.StatusOK, response.StatusCode)
	require.Equal(t, "pending", submitResp.Status)
	require.NotEmpty(t, submitResp.ApprovalID)
	require.NotEmpty(t, submitResp.RequestID)

	// Requester status surface lists the pending request with both expiries.
	var listResp struct {
		Requests []struct {
			ApprovalID            string `json:"approvalId"`
			ScopeType             string `json:"scopeType"`
			ScopeID               string `json:"scopeId"`
			Status                string `json:"status"`
			CollaboratorExpiresAt string `json:"collaboratorExpiresAt"`
			ApprovalExpiresAt     string `json:"approvalExpiresAt"`
		} `json:"requests"`
	}
	response = testkit.DoJSON(t, client, http.MethodGet, server.URL+"/api/v1/workspaces/"+workspaceID+"/collaborator-requests", nil, testkit.WorkspaceHeaders(requester.AccessToken, workspaceID), &listResp)
	require.Equal(t, http.StatusOK, response.StatusCode)
	require.Len(t, listResp.Requests, 1)
	request := listResp.Requests[0]
	require.Equal(t, "pending", request.Status)
	require.Equal(t, "task", request.ScopeType)
	require.Equal(t, taskScopeID, request.ScopeID)
	require.NotEmpty(t, request.CollaboratorExpiresAt, "collaborator expiry must be reported")
	require.NotEmpty(t, request.ApprovalExpiresAt, "7-day approval validity must be reported separately")
}
