package tools

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"sync"
	"testing"

	"security-center-mcp/internal/client"
)

// whoamiRecordedCall captures the single request the whoami tool should
// issue: a fixed, bodyless GET against the identity endpoint.
type whoamiRecordedCall struct {
	Method string
	Path   string
	Query  string
	APIKey string
}

// newWhoamiMockBackend starts one httptest server answering
// GET /api/v1/agent/whoami with the staged payload (or the error
// envelope when payload is a business error) and recording the request.
func newWhoamiMockBackend(t *testing.T, statusCode int, responseBody string) (*client.Client, func() *whoamiRecordedCall) {
	t.Helper()
	var mu sync.Mutex
	var call *whoamiRecordedCall
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mu.Lock()
		call = &whoamiRecordedCall{
			Method: r.Method,
			Path:   r.URL.Path,
			Query:  r.URL.RawQuery,
			APIKey: r.Header.Get("X-API-Key"),
		}
		mu.Unlock()
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(statusCode)
		fmt.Fprint(w, responseBody)
	}))
	t.Cleanup(srv.Close)
	c := &client.Client{BaseURL: srv.URL, APIKey: "test-key", HTTP: srv.Client()}
	return c, func() *whoamiRecordedCall {
		mu.Lock()
		defer mu.Unlock()
		return call
	}
}

func TestWhoamiPassesIdentityThrough(t *testing.T) {
	c, recorded := newWhoamiMockBackend(t, http.StatusOK,
		`{"code":0,"message":"ok","data":{"actor_type":"agent","agent_id":12,"agent_name":"sec-bot","user_id":7,"name":"User A","email":"a@example.com","employee_id":88,"permission_scope":["vuln:view_findings"]},"timestamp":1}`)

	data, err := Dispatch(context.Background(), c, "whoami", map[string]any{})
	if err != nil {
		t.Fatalf("Dispatch whoami: %v", err)
	}
	payload, ok := data.(map[string]any)
	if !ok {
		t.Fatalf("whoami data not passed through as an object: %v", data)
	}
	if payload["actor_type"] != "agent" || payload["user_id"] != float64(7) || payload["employee_id"] != float64(88) {
		t.Fatalf("whoami data not passed through verbatim: %v", payload)
	}
	scope, ok := payload["permission_scope"].([]any)
	if !ok || len(scope) != 1 || scope[0] != "vuln:view_findings" {
		t.Fatalf("permission_scope not passed through: %v", payload["permission_scope"])
	}

	call := recorded()
	if call == nil {
		t.Fatal("backend received no request")
	}
	if call.Method != http.MethodGet || call.Path != "/api/v1/agent/whoami" {
		t.Fatalf("request = %s %s, want GET /api/v1/agent/whoami", call.Method, call.Path)
	}
	if call.Query != "" {
		t.Fatalf("whoami must not send query parameters, got %q", call.Query)
	}
	if call.APIKey != "test-key" {
		t.Fatalf("X-API-Key = %q, want the configured key", call.APIKey)
	}
}

func TestWhoamiBackendErrorBecomesStructuredResult(t *testing.T) {
	c, _ := newWhoamiMockBackend(t, http.StatusOK,
		`{"code":401,"message":"invalid api key","data":null,"timestamp":1}`)

	data, err := Dispatch(context.Background(), c, "whoami", map[string]any{})
	if err != nil {
		t.Fatalf("Dispatch whoami: want structured result, got Go error %v", err)
	}
	payload, ok := data.(map[string]any)
	if !ok {
		t.Fatalf("whoami error payload not an object: %v", data)
	}
	e, ok := payload["error"].(map[string]any)
	if !ok || e["code"] != 401 {
		t.Fatalf("whoami error payload = %v, want error.code 401", payload)
	}
}
