package zitadel_test

import (
	"context"
	"testing"
	"time"

	"gateway/internal/library/zitadel"

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

func TestVerifyIDToken(t *testing.T) {
	t.Parallel()

	fix := newJWKSFixture(t)
	now := time.Now().UTC()
	raw := fix.signIDToken(t, fix.validClaims(now))

	claims := fix.verify(t, raw)
	require.Equal(t, "zitadel-sub-1", claims.Sub)
	require.Equal(t, "user@example.com", claims.Email)
	require.True(t, claims.EmailVerified)

	_, err := fix.Client.VerifyIDToken(context.Background(), raw[:len(raw)-2]+"xx")
	require.ErrorIs(t, err, zitadel.ErrInvalidIDToken)
}

func TestVerifyIDTokenExpired(t *testing.T) {
	t.Parallel()

	fix := newJWKSFixture(t)
	now := time.Now().UTC()
	claims := fix.validClaims(now)
	claims["exp"] = now.Add(-time.Hour).Unix()
	raw := fix.signIDToken(t, claims)

	_, err := fix.Client.VerifyIDToken(context.Background(), raw)
	require.ErrorIs(t, err, zitadel.ErrInvalidIDToken)
	require.Contains(t, err.Error(), "expired")
}

func TestVerifyIDTokenWrongIssuer(t *testing.T) {
	t.Parallel()

	fix := newJWKSFixture(t)
	now := time.Now().UTC()
	claims := fix.validClaims(now)
	claims["iss"] = "https://evil.example.com"
	raw := fix.signIDToken(t, claims)

	_, err := fix.Client.VerifyIDToken(context.Background(), raw)
	require.ErrorIs(t, err, zitadel.ErrInvalidIDToken)
	require.Contains(t, err.Error(), "iss")
}

func TestVerifyIDTokenWrongAudience(t *testing.T) {
	t.Parallel()

	fix := newJWKSFixture(t)
	now := time.Now().UTC()
	claims := fix.validClaims(now)
	claims["aud"] = "other-client"
	raw := fix.signIDToken(t, claims)

	_, err := fix.Client.VerifyIDToken(context.Background(), raw)
	require.ErrorIs(t, err, zitadel.ErrInvalidIDToken)
	require.Contains(t, err.Error(), "aud")
}

func TestVerifyIDTokenAcceptsIssuerWithTrailingSlash(t *testing.T) {
	t.Parallel()

	fix := newJWKSFixture(t)
	now := time.Now().UTC()
	claims := fix.validClaims(now)
	claims["iss"] = fix.Issuer + "/"
	raw := fix.signIDToken(t, claims)

	claimsOut := fix.verify(t, raw)
	require.Equal(t, "zitadel-sub-1", claimsOut.Sub)
}

func TestVerifyIDTokenNotConfigured(t *testing.T) {
	t.Parallel()

	var client *zitadel.Client
	_, err := client.VerifyIDToken(context.Background(), "any.token.here")
	require.ErrorIs(t, err, zitadel.ErrNotConfigured)
}
