package server

import (
	"errors"
	"time"

	"buf.build/go/protovalidate"
	"github.com/golang-jwt/jwt/v5"
	"google.golang.org/protobuf/encoding/protojson"
)

func (c *WebSocketTokenClaims) GetExpirationTime() (*jwt.NumericDate, error) {
	return toJWTNumericDate(c.GetRegisteredClaimExpiresAt()), nil
}

func (c *WebSocketTokenClaims) GetIssuedAt() (*jwt.NumericDate, error) {
	return toJWTNumericDate(c.GetRegisteredClaimIssuedAt()), nil
}

func (c *WebSocketTokenClaims) GetNotBefore() (*jwt.NumericDate, error) {
	return toJWTNumericDate(c.GetRegisteredClaimNotBefore()), nil
}

func (c *WebSocketTokenClaims) GetIssuer() (string, error) {
	return c.GetRegisteredClaimIssuer(), nil
}

func (c *WebSocketTokenClaims) GetSubject() (string, error) {
	return c.GetRegisteredClaimSubject(), nil
}

func (c *WebSocketTokenClaims) GetAudience() (jwt.ClaimStrings, error) {
	return c.GetRegisteredClaimAudience(), nil
}

func toJWTNumericDate(t int64) *jwt.NumericDate {
	return jwt.NewNumericDate(time.Unix(t, 0))
}

func (c *WebSocketTokenClaims) MarshalJSON() ([]byte, error) {
	return protojson.Marshal(c)
}

func (c *WebSocketTokenClaims) UnmarshalJSON(b []byte) error {
	return protojson.Unmarshal(b, c)
}

type ValidatingWebSocketTokenClaims struct {
	WebSocketTokenClaims

	Validator        protovalidate.Validator
	ValidForEndpoint string
}

func (v *ValidatingWebSocketTokenClaims) Validate() error {
	err := v.Validator.Validate(&v.WebSocketTokenClaims)
	if err != nil {
		return err
	}

	if e := v.GetEndpoint(); e != v.ValidForEndpoint {
		return errors.New("token has invalid endpoint")
	}
	return nil
}
