package entity

import (
	"time"

	"github.com/golang-jwt/jwt/v4"
)

// Token represents a token entity stored in Redis
type Token struct {
	ID               string    `json:"id"`                 // Token ID (KSUID)
	UID              string    `json:"uid"`                // User ID
	DeviceID         string    `json:"device_id"`          // Device ID
	AccessToken      string    `json:"access_token"`       // JWT access token
	RefreshToken     string    `json:"refresh_token"`      // SHA256 refresh token
	ExpiresIn        int       `json:"expires_in"`         // Access token expiry (Unix timestamp)
	RefreshExpiresIn int       `json:"refresh_expires_in"` // Refresh token expiry (Unix timestamp)
	AccessCreateAt   time.Time `json:"access_create_at"`   // Access token creation time
	RefreshCreateAt  time.Time `json:"refresh_create_at"`  // Refresh token creation time
}

// IsExpired checks if the access token is expired
func (t *Token) IsExpired() bool {
	return time.Now().Unix() > int64(t.ExpiresIn)
}

// IsRefreshExpired checks if the refresh token is expired
func (t *Token) IsRefreshExpired() bool {
	return time.Now().Unix() > int64(t.RefreshExpiresIn)
}

// RedisRefreshExpiredSec returns the refresh token expiry duration in seconds
func (t *Token) RedisRefreshExpiredSec() int {
	now := time.Now().Unix()
	if int64(t.RefreshExpiresIn) <= now {
		return 0
	}
	return t.RefreshExpiresIn - int(now)
}

// Ticket represents a one-time token ticket
type Ticket struct {
	Data  map[string]string `json:"data"`  // Token claims data
	Token Token             `json:"token"` // Associated token
}

// Claims represents JWT claims structure
type Claims struct {
	jwt.RegisteredClaims
	Data interface{} `json:"data"`
}

// Validate validates the token entity
func (t *Token) Validate() error {
	if t.ID == "" {
		return ErrInvalidTokenID
	}
	if t.UID == "" {
		return ErrInvalidUID
	}
	if t.AccessToken == "" {
		return ErrInvalidAccessToken
	}
	return nil
}
