-- name: InsertSession :one
-- created_ip and last_ip start equal: at issue time the origin IS the current
-- location. They diverge as the session is used from elsewhere, which is what
-- makes a stolen token visible in the active-sessions surface.
INSERT INTO sessions (user_id, token_hash, user_agent, created_ip, last_ip)
VALUES ($1, $2, $3, sqlc.arg(ip), sqlc.arg(ip))
RETURNING *;

-- name: GetSessionByTokenHash :one
SELECT * FROM sessions WHERE token_hash = $1;

-- name: TouchSessionLastSeen :exec
UPDATE sessions SET last_seen_at = now(), last_ip = $2 WHERE id = $1;

-- name: ListSessionsForUser :many
-- Most-recently-active first: the row a user is most likely to act on is the
-- one that moved last, and an unfamiliar entry at the top is the alarm.
SELECT * FROM sessions WHERE user_id = $1 ORDER BY last_seen_at DESC;

-- name: DeleteSession :exec
DELETE FROM sessions WHERE id = $1;

-- name: DeleteSessionByTokenHash :exec
DELETE FROM sessions WHERE token_hash = $1;

-- name: DeleteSessionForUser :execrows
-- Scoped by user_id, not just id (rule #47). Keyed on the id alone, any
-- household member could revoke another member's session by guessing a uuid.
-- execrows lets the handler answer 404 rather than a false 204 when the row
-- isn't theirs.
DELETE FROM sessions WHERE id = $1 AND user_id = $2;

-- name: DeleteOtherSessionsForUser :execrows
-- "Log out everywhere else." Excludes the caller's own session so the action
-- doesn't log them out of the page they just used to invoke it.
DELETE FROM sessions WHERE user_id = $1 AND id <> $2;
