-- Time-boxed "not right now" on a Discover artist suggestion (#2374).
--
-- See 0049_suggestion_snoozes.up.sql for why this is a snooze and not a
-- dismissal: it records no verdict on the music, expires on its own, and
-- must never reach the taste profile. Nothing in internal/taste may read
-- this table.

-- name: SnoozeSuggestion :exec
-- Upsert, so re-snoozing an already-snoozed candidate EXTENDS it instead of
-- erroring on the PK. The name is refreshed too — a later suggestion may
-- carry a corrected spelling from the similarity feed.
-- $1=user_id, $2=candidate_mbid, $3=candidate_name, $4=duration in days.
INSERT INTO suggestion_snoozes (user_id, candidate_mbid, candidate_name, snoozed_until)
VALUES ($1, $2, $3, now() + ($4::float8 * INTERVAL '1 day'))
ON CONFLICT (user_id, candidate_mbid) DO UPDATE
   SET snoozed_until  = EXCLUDED.snoozed_until,
       candidate_name = EXCLUDED.candidate_name;

-- name: UnsnoozeSuggestion :execrows
-- Row count is returned so the handler can 404 an MBID that was never
-- snoozed rather than reporting success for a no-op.
DELETE FROM suggestion_snoozes
 WHERE user_id = $1 AND candidate_mbid = $2;

-- name: ListActiveSuggestionSnoozes :many
-- Backs the manage / un-snooze surface. Expired rows are filtered HERE
-- rather than left to the sweeper: gc runs on an hourly tick, so a row can
-- outlive its expiry by up to a tick and must not read as still-snoozed in
-- the meantime.
SELECT candidate_mbid, candidate_name, snoozed_until, created_at
  FROM suggestion_snoozes
 WHERE user_id = $1 AND snoozed_until > now()
 ORDER BY snoozed_until, candidate_mbid;

-- name: GcDeleteExpiredSuggestionSnoozes :execrows
-- Keeps the table from growing without bound. Every read already filters on
-- snoozed_until > now(), so deleting an expired row changes no behaviour —
-- this is purely reclamation.
DELETE FROM suggestion_snoozes WHERE snoozed_until < now();
