package session

import "context"

// Platform is the trusted execution context recorded on a session: the wrapper
// Kind the session was established through and the device Subtype. An empty Kind
// marks an untrusted session — one minted before platform capture, or one the
// gateway could not attribute — which the payments compliance gate treats as
// view-only.
//
// Kind is always trustworthy: it is derived server-side from the validated
// establish path, never from a client-supplied field. Subtype is trustworthy only
// for VK (vk_platform rides inside the signed launch params); for telegram and
// direct it is client-reported and best-effort, so the gate must never rely on it.
type Platform struct {
	Kind    string
	Subtype string
}

// Platform kinds recorded in platform_kind.
const (
	PlatformKindVK       = "vk"
	PlatformKindTelegram = "telegram"
	PlatformKindDirect   = "direct"
)

// Platform subtypes recorded in platform_subtype.
const (
	SubtypeIOS     = "ios"
	SubtypeAndroid = "android"
	SubtypeWeb     = "web"
)

// Trusted reports whether the session was attributed to a platform (a non-empty
// Kind). The zero Platform is untrusted.
func (p Platform) Trusted() bool { return p.Kind != "" }

// NormalizeSubtype coerces subtype to one of the known device families, defaulting
// an empty or unrecognised value to web. A newly established session always carries
// at least a web subtype, so a trusted session is never left without one.
func NormalizeSubtype(subtype string) string {
	switch subtype {
	case SubtypeIOS, SubtypeAndroid, SubtypeWeb:
		return subtype
	default:
		return SubtypeWeb
	}
}

// platformCtxKey types the request-context slot the trusted platform rides in.
type platformCtxKey struct{}

// WithPlatform returns a copy of ctx carrying platform. The backend middleware
// calls it after parsing the gateway-injected X-Platform header, so downstream
// handlers and the link/merge session mint read the caller's platform from ctx.
func WithPlatform(ctx context.Context, platform Platform) context.Context {
	return context.WithValue(ctx, platformCtxKey{}, platform)
}

// PlatformFromContext returns the platform stored by WithPlatform and whether one
// was present. A missing value yields the zero (untrusted) Platform.
func PlatformFromContext(ctx context.Context) (Platform, bool) {
	p, ok := ctx.Value(platformCtxKey{}).(Platform)
	return p, ok
}
