package agsbridge

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
)

const DefaultAuthHeader = "Authorization"

// WorkloadSubject is the single AGS identity used by MeshX-owned repository work.
const WorkloadSubject = "meshx-internal"

func AuthorizationHeader() string {
	header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"none","typ":"JWT"}`))
	claims, err := json.Marshal(map[string]any{
		"sub":                WorkloadSubject,
		"preferred_username": WorkloadSubject,
		"name":               WorkloadSubject,
	})
	if err != nil {
		panic("marshal static MeshX AGS workload identity: " + err.Error())
	}
	payload := base64.RawURLEncoding.EncodeToString(claims)
	return "Bearer " + header + "." + payload + "."
}

func AuthHeader(header string) string {
	if trimmed := strings.TrimSpace(header); trimmed != "" {
		return trimmed
	}
	return DefaultAuthHeader
}

func SetAuthHeader(headers http.Header, configuredHeader string, value string) {
	value = strings.TrimSpace(value)
	if value == "" {
		return
	}
	headers.Set(AuthHeader(configuredHeader), value)
}

func GetAuthHeader(headers http.Header, configuredHeader string) string {
	header := AuthHeader(configuredHeader)
	if value := strings.TrimSpace(headers.Get(header)); value != "" {
		return value
	}
	if !strings.EqualFold(header, DefaultAuthHeader) {
		return strings.TrimSpace(headers.Get(DefaultAuthHeader))
	}
	return ""
}

func DoJSONRequest(ctx context.Context, handler http.Handler, authHeader string, authorizationHeader string, method string, path string, payload any) *httptest.ResponseRecorder {
	var body io.Reader
	if payload != nil {
		encoded, _ := json.Marshal(payload)
		body = bytes.NewReader(encoded)
	}
	request := httptest.NewRequest(method, path, body).WithContext(ContextWithSiteAdmin(ctx))
	if payload != nil {
		request.Header.Set("Content-Type", "application/json")
	}
	SetAuthHeader(request.Header, authHeader, authorizationHeader)
	recorder := httptest.NewRecorder()
	handler.ServeHTTP(recorder, request)
	return recorder
}
