package hostruntime

import (
	"context"
	"time"
)

// UserSession is the host-runtime authenticated session shape carried across
// HTTP middleware boundaries.
type UserSession struct {
	ID                string
	Name              string
	Email             string
	ProfileID         string
	ProfileName       string
	RoleID            *string
	RoleName          *string
	ConnectedAppID    string
	Scope             string
	GrantType         string
	SessionClass      string
	SystemPermissions map[string]bool
}

// SessionClaims is the validated bearer-token result consumed by auth
// middleware. SessionID is the non-secret JWT/session identifier.
type SessionClaims struct {
	SessionID string
	User      UserSession
}

// SessionAuthenticator validates bearer tokens and updates session activity
// without exposing the host runtime to a concrete kernel auth service.
type SessionAuthenticator interface {
	ValidateSession(ctx context.Context, bearerToken string) (*SessionClaims, error)
	TouchSession(ctx context.Context, sessionID string)
}

// SessionRenewingAuthenticator is an optional additive extension implemented by
// a SessionAuthenticator that can return a replacement bearer credential from
// the same operation that validates the submitted bearer. An empty replacement
// means validation succeeded without renewing the credential.
type SessionRenewingAuthenticator interface {
	SessionAuthenticator
	ValidateSessionWithRenewal(ctx context.Context, bearerToken string) (*SessionClaims, string, error)
}

// SessionControlValidation is the transport result of control-aware bearer
// validation. ProofCookieExpiresAt is zero unless the submitted opaque proof
// was validated and the operation renewed or recovered the browser session.
// A nonzero value asks the protected response boundary to reissue the same
// proof cookie through that durable expiry.
type SessionControlValidation struct {
	Claims               *SessionClaims
	RefreshedBearerToken string
	ProofCookieExpiresAt time.Time
}

// SessionControlAuthenticator is the preferred additive renewal extension for
// admitted first-party browser sessions. The control proof is an opaque,
// independently held session credential. Implementations own proof validation
// and MUST treat an empty or invalid proof as insufficient authority to recover
// or replace a superseded bearer or to return a nonzero ProofCookieExpiresAt.
//
// An admitted request without a proof cookie deliberately calls this method
// with an empty proof and does not fall back to SessionRenewingAuthenticator.
// Requests that do not opt into browser session-control admission retain the
// additive SessionRenewingAuthenticator behavior.
type SessionControlAuthenticator interface {
	SessionAuthenticator
	ValidateSessionWithControl(ctx context.Context, bearerToken, controlProof string) (SessionControlValidation, error)
}

// BrowserSessionValidation is the transport result of validating a first-party
// browser session from its session-control proof alone.
//
// It deliberately has no bearer field. The browser lane exists so the page never
// holds a JS-readable credential, so there is no shape in which this result can
// hand a bearer back to the browser — the omission is the contract, not an
// oversight.
//
// ProofCookieExpiresAt is zero unless the operation renewed the durable session.
// A nonzero value asks the protected response boundary to reissue the same proof
// cookie through that durable expiry; it never asks for a new proof value.
type BrowserSessionValidation struct {
	Claims               *SessionClaims
	ProofCookieExpiresAt time.Time
}

// BrowserSessionAuthenticator resolves an admitted first-party browser session
// from the session-control proof, with no bearer credential involved.
//
// This is the cookie-only counterpart to SessionControlAuthenticator, which still
// requires a bearer and compares the proof against it. Implementations own proof
// validation and MUST treat an empty, malformed, expired, revoked, or ambiguous
// proof as no authority at all: no claims, and a zero ProofCookieExpiresAt.
//
// "Ambiguous" is explicit because the proof is the whole lookup key. If two
// durable sessions carry the same verifier, an implementation must refuse rather
// than choose one, since choosing would decide which principal the request
// authenticates as.
type BrowserSessionAuthenticator interface {
	SessionAuthenticator
	ValidateBrowserSession(ctx context.Context, controlProof string) (BrowserSessionValidation, error)
}
