// Package session defines the authenticated session-cache contract used by the
// gateway hot path.
package session

import (
	"context"
	"errors"
)

var (
	// ErrNotFound reports that SessionCache does not currently contain the
	// requested device session identifier.
	ErrNotFound = errors.New("session cache record not found")
)

// Cache resolves authenticated device-session state from the gateway
// hot path. The canonical implementation is *MemoryCache: a
// process-local LRU + TTL store that falls back to backend's
// `/api/v1/internal/sessions/{id}` on miss and listens for
// `session_invalidation` push events from backend so revoked sessions
// are reflected immediately without a fresh backend lookup.
//
// The Mark* methods are called by the push dispatcher. They flip
// cached entries to revoked status; subsequent Lookups serve the
// revoked record directly so authenticated traffic on those sessions
// is rejected at the edge before reaching backend.
type Cache interface {
	// Lookup returns the cached record for deviceSessionID. Implementations must
	// wrap ErrNotFound when the cache does not contain the requested record.
	Lookup(ctx context.Context, deviceSessionID string) (Record, error)

	// MarkRevoked flips the cached record for deviceSessionID to a
	// revoked status. Calling on a missing entry is a no-op.
	MarkRevoked(deviceSessionID string)

	// MarkAllRevokedForUser flips every cached record belonging to
	// userID to a revoked status. Calling on a user with no cached
	// sessions is a no-op.
	MarkAllRevokedForUser(userID string)
}

// Status identifies the cached lifecycle state of a device session.
type Status string

const (
	// StatusActive reports that the cached device session may continue through
	// later authenticated gateway checks.
	StatusActive Status = "active"

	// StatusRevoked reports that the cached device session has been revoked and
	// must be rejected before later auth steps run.
	StatusRevoked Status = "revoked"
)

// Record is the minimum authenticated session state required by the gateway
// before signature verification begins.
type Record struct {
	// DeviceSessionID is the stable device-session identifier resolved from the
	// hot-path cache.
	DeviceSessionID string

	// UserID is the authenticated user identity bound to DeviceSessionID.
	UserID string

	// ClientPublicKey is the standard base64-encoded raw Ed25519 public key
	// material used for request-signature verification.
	ClientPublicKey string

	// Status reports whether the cached session is active or revoked.
	Status Status

	// RevokedAtMS optionally records when the device session was revoked.
	RevokedAtMS *int64
}

// IsKnown reports whether s is one of the session states supported by the
// gateway.
func (s Status) IsKnown() bool {
	switch s {
	case StatusActive, StatusRevoked:
		return true
	default:
		return false
	}
}
