package capability

import (
	"crypto/ed25519"
	"encoding/base64"
	"encoding/json"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestLoadSignerFromFileSignsEdDSAJWT(t *testing.T) {
	publicKey, privateKey, err := ed25519.GenerateKey(nil)
	require.NoError(t, err)

	keyFile := filepath.Join(t.TempDir(), "capability-ed25519.json")
	rawKey, err := json.Marshal(devCapabilityKeyFile{
		KeyID:      "dev",
		PublicKey:  base64.StdEncoding.EncodeToString(publicKey),
		PrivateKey: base64.StdEncoding.EncodeToString(privateKey),
	})
	require.NoError(t, err)
	require.NoError(t, os.WriteFile(keyFile, rawKey, 0o600))

	signer, err := LoadSignerFromFile(keyFile)
	require.NoError(t, err)

	token, err := signer.Sign(Claims{
		Issuer:              DefaultIssuer,
		Subject:             "lps_test",
		Audience:            Audience{DefaultAudience},
		ExpiresAt:           1780318500,
		NotBefore:           1780317600,
		CapabilitySessionID: "lps_test",
		OrganizationID:      "org_test",
		WorkspaceID:         "wsp_test",
		AgentID:             "agt_test",
		MemberID:            "mem_test",
		RuntimeSessionID:    "ars_test",
		AuthorityGeneration: 1,
		IssuedAt:            1780317600,
	})
	require.NoError(t, err)

	parts := strings.Split(token, ".")
	require.Len(t, parts, 3)
	headerRaw, err := base64.RawURLEncoding.DecodeString(parts[0])
	require.NoError(t, err)
	var header map[string]string
	require.NoError(t, json.Unmarshal(headerRaw, &header))
	require.Equal(t, map[string]string{"alg": "EdDSA", "kid": "dev", "typ": "JWT"}, header)

	payloadRaw, err := base64.RawURLEncoding.DecodeString(parts[1])
	require.NoError(t, err)
	var payload map[string]any
	require.NoError(t, json.Unmarshal(payloadRaw, &payload))
	require.Equal(t, DefaultIssuer, payload["iss"])
	require.Equal(t, DefaultAudience, payload["aud"])
	require.Equal(t, "org_test", payload["organization_id"])
	require.Equal(t, "ars_test", payload["runtime_session_id"])

	signature, err := base64.RawURLEncoding.DecodeString(parts[2])
	require.NoError(t, err)
	require.True(t, ed25519.Verify(publicKey, []byte(parts[0]+"."+parts[1]), signature))
}
