// Tests for the M13a W5 JWT gate in deliverd-telegram.
// Mirrors cmd/deliverd-fcm/admin_test.go but for the
// telegram channel. The actual DLQ handlers need a real
// Postgres pool; those paths are covered by the M8 smoke
// and the m13a E2E.
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"io"
	"log/slog"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"time"
)

const testSecret = "test-secret-with-32-bytes-min-len-abc"

func mintTestJWT(t *testing.T, secret, role string) string {
	t.Helper()
	hb, _ := json.Marshal(map[string]string{"alg": "HS256", "typ": "JWT"})
	body, _ := json.Marshal(map[string]any{
		"sub":  "u-test",
		"tid":  "t-test",
		"role": role,
		"typ":  "access",
		"iss":  "broad-announce",
		"exp":  time.Now().Add(15 * time.Minute).Unix(),
		"iat":  time.Now().Unix(),
	})
	enc := base64.RawURLEncoding.EncodeToString(hb) + "." + base64.RawURLEncoding.EncodeToString(body)
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(enc))
	return enc + "." + base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
}

func discardLogger() *slog.Logger {
	return slog.New(slog.NewTextHandler(io.Discard, nil))
}

func TestWireAdminRoutes_NoSecret_Disabled(t *testing.T) {
	os.Unsetenv("BA_AUTHD_JWT_SECRET")
	mux := http.NewServeMux()
	wireAdminRoutes(mux, nil, discardLogger())
	for _, tc := range []struct{ method, path string }{
		{"GET", "/v1/admin/dlq"},
		{"GET", "/v1/admin/dlq/1"},
	} {
		rr := httptest.NewRecorder()
		mux.ServeHTTP(rr, httptest.NewRequest(tc.method, tc.path, nil))
		if rr.Code != http.StatusNotFound {
			t.Errorf("%s %s with no secret: got %d, want 404", tc.method, tc.path, rr.Code)
		}
	}
}

func TestWireAdminRoutes_WithSecret_Gated(t *testing.T) {
	t.Setenv("BA_AUTHD_JWT_SECRET", testSecret)
	t.Setenv("BA_AUTHD_ISSUER", "broad-announce")
	mux := http.NewServeMux()
	wireAdminRoutes(mux, nil, discardLogger())
	for _, tc := range []struct{ method, path string }{
		{"GET", "/v1/admin/dlq"},
		{"GET", "/v1/admin/dlq/1"},
	} {
		rr := httptest.NewRecorder()
		mux.ServeHTTP(rr, httptest.NewRequest(tc.method, tc.path, nil))
		if rr.Code != http.StatusUnauthorized {
			t.Errorf("%s %s with secret+no-token: status = %d, want 401", tc.method, tc.path, rr.Code)
		}
	}
}

func TestAdminDLQ_AnyAuthenticatedUser_CanList(t *testing.T) {
	t.Setenv("BA_AUTHD_JWT_SECRET", testSecret)
	mux := http.NewServeMux()
	wireAdminRoutes(mux, nil, discardLogger())
	for _, role := range []string{"viewer", "tenant_admin", "super_admin"} {
		t.Run(role, func(t *testing.T) {
			tok := mintTestJWT(t, testSecret, role)
			req := httptest.NewRequest("GET", "/v1/admin/dlq", nil)
			req.Header.Set("Authorization", "Bearer "+tok)
			rr := httptest.NewRecorder()
			func() {
				defer func() { _ = recover() }()
				mux.ServeHTTP(rr, req)
			}()
			if rr.Code == http.StatusUnauthorized || rr.Code == http.StatusForbidden {
				t.Errorf("%s: status = %d, want gate passed (500/panic expected)", role, rr.Code)
			}
		})
	}
}
