package attestations

import (
	"net/http"
	"strings"
	"testing"

	"github.com/jmrplens/gitlab-mcp-server/v2/internal/testutil"
	"github.com/jmrplens/gitlab-mcp-server/v2/internal/toolutil"
)

const registerAttestationsJSON = `[{"iid":1,"bundle":{"mediaType":"application/vnd.in-toto+json","content":{"_type":"https://in-toto.io/Statement/v1"}}}]`

// TestActionSpecs_Metadata verifies attestation action spec metadata.
func TestActionSpecs_Metadata(t *testing.T) {
	client := testutil.NewTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
	}))
	specs := ActionSpecs(client)
	if len(specs) != 2 {
		t.Fatalf("len(ActionSpecs) = %d, want 2", len(specs))
	}
	for _, spec := range specs {
		if !spec.ReadOnly || !spec.Idempotent || spec.OwnerPackage != "attestations" {
			t.Fatalf("unexpected ActionSpec semantics: %+v", spec)
		}
	}
}

// TestActionSpecs_CallRoutes verifies both attestation canonical routes execute successfully.
func TestActionSpecs_CallRoutes(t *testing.T) {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		path := r.URL.Path
		switch {
		case r.Method == http.MethodGet && strings.Contains(path, "sha256:abc123"):
			testutil.RespondJSON(w, http.StatusOK, registerAttestationsJSON)
		case r.Method == http.MethodGet && strings.Contains(path, "/attestations/"):
			w.WriteHeader(http.StatusOK)
			_, _ = w.Write([]byte(`{"_type":"attestation"}`))
		default:
			http.NotFound(w, r)
		}
	})
	client := testutil.NewTestClient(t, mux)
	specs := ActionSpecs(client)
	specByTool := make(map[string]toolutil.ActionSpec, len(specs))
	for _, spec := range specs {
		specByTool[spec.IndividualTool.Name] = spec
	}

	tools := []struct {
		name string
		args map[string]any
	}{
		{"gitlab_list_attestations", map[string]any{"project_id": "42", "subject_digest": "sha256:abc123"}},
		{"gitlab_download_attestation", map[string]any{"project_id": "42", "attestation_iid": float64(1)}},
	}
	for _, tt := range tools {
		t.Run(tt.name, func(t *testing.T) {
			spec, ok := specByTool[tt.name]
			if !ok {
				t.Fatalf("missing ActionSpec for %s", tt.name)
			}
			result, err := spec.Route.Handler(t.Context(), tt.args)
			if err != nil {
				t.Fatalf("Route.Handler(%s) error: %v", tt.name, err)
			}
			if result == nil {
				t.Fatalf("Route.Handler(%s) returned nil", tt.name)
			}
		})
	}
}
