package webui

import (
	"net/http"
	"sync"

	"github.com/ProtonMail/go-crypto/openpgp"
)

// pgpKeyCache holds unlocked PGP identities for the rest of a login session —
// mirrors smimeKeyCache (webmail_smime_cache.go), but caches the whole *openpgp.Entity
// (not just a raw private key) since decrypting a PGP message needs subkey lookup on
// the entity itself, not a bare key value. Kept as its own type rather than
// generalizing smimeKeyCache into an any-typed cache — both stay simply and
// correctly typed.
type pgpKeyCache struct {
	mu    sync.Mutex
	byTok map[string]map[int64]*openpgp.Entity
}

func newPGPKeyCache() *pgpKeyCache {
	return &pgpKeyCache{byTok: map[string]map[int64]*openpgp.Entity{}}
}

func (c *pgpKeyCache) get(token string, identityID int64) (*openpgp.Entity, bool) {
	c.mu.Lock()
	defer c.mu.Unlock()
	keys, ok := c.byTok[token]
	if !ok {
		return nil, false
	}
	entity, ok := keys[identityID]
	return entity, ok
}

func (c *pgpKeyCache) put(token string, identityID int64, entity *openpgp.Entity) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.byTok[token] == nil {
		c.byTok[token] = map[int64]*openpgp.Entity{}
	}
	c.byTok[token][identityID] = entity
}

// clearSession drops every unlocked identity for one session — called on logout so
// a key never outlives the session it was unlocked in. Same ponytail-flagged
// simplification as smimeKeyCache.clearSession: memory-bounded by active sessions,
// not TTL'd against a session that expires without an explicit logout.
func (c *pgpKeyCache) clearSession(token string) {
	c.mu.Lock()
	defer c.mu.Unlock()
	delete(c.byTok, token)
}

// sessionToken reads the raw webmail session cookie value, used as the PGP key
// cache's key — separate from mailboxFromContext, which only exposes the resolved
// *db.Mailbox, not the token itself.
func sessionToken(r *http.Request) string {
	c, err := r.Cookie(mailboxSessionCookieName)
	if err != nil {
		return ""
	}
	return c.Value
}
