-- name: UpsertClipboard :one
-- New rows start version 1; conflicts bump version by 1 (per-user monotonic).
-- LWW: the DO UPDATE only runs when the new origin_ts is strictly greater than
-- the stored one, so a delayed / out-of-order older copy changes nothing and
-- RETURNING yields no row (the service reads sql.ErrNoRows as "stale, rejected").
INSERT INTO clipboard_state (user_id, content_type, content, source_device, updated_at, version, origin_ts)
VALUES (?, ?, ?, ?, ?, 1, ?)
ON CONFLICT (user_id) DO UPDATE SET
    content_type  = excluded.content_type,
    content       = excluded.content,
    source_device = excluded.source_device,
    updated_at    = excluded.updated_at,
    version       = clipboard_state.version + 1,
    origin_ts     = excluded.origin_ts
WHERE excluded.origin_ts > clipboard_state.origin_ts
RETURNING version;

-- name: GetClipboard :one
SELECT user_id, content_type, content, source_device, updated_at, version, origin_ts
FROM clipboard_state
WHERE user_id = ?;

-- ClearExpiredClipboards empties content older than the cutoff (content /
-- source_device set NULL) for the short-TTL exposure limit; the row is kept.
-- Called periodically by the clipboard sweeper.
--
-- ASCII only: sqlc 1.31.x miscomputes byte offsets on multibyte comments and
-- truncates the generated SQL const. This query was silently cut to "SET content ="
-- (the sweeper then failed at runtime with "incomplete input"). Keep ASCII.
-- name: ClearExpiredClipboards :execrows
UPDATE clipboard_state
SET content = NULL, source_device = NULL
WHERE content IS NOT NULL AND updated_at < ?;
