-- Household co-play similarity (#1533, milestone #160 Opt 5). Minstrel is a
-- single shared-library, multi-user server (no per-user library ACL), so the
-- "household" is the whole instance's user set. These queries recompute
-- artist–artist co-occurrence edges from play_events and store them in
-- artist_similarity under the pre-provisioned source = 'user_cooccurrence'
-- (whitelisted in the 0009 CHECK from day one). A periodic worker DELETEs then
-- re-INSERTs so edges that fall below threshold disappear. Single-user servers
-- produce no edges (the >= 2 co-player gate), so the arm is empty there.

-- name: DeleteArtistCoplayEdges :exec
DELETE FROM artist_similarity WHERE source = 'user_cooccurrence';

-- name: InsertArtistCoplayEdges :exec
-- Two artists are "co-played" when the same users play both. score is the
-- Jaccard of their distinct-player sets — coplayers / (playersA + playersB −
-- coplayers) in (0,1] — which controls for globally-popular artists (an artist
-- everyone plays would otherwise co-occur with everything). Only pairs with
-- >= 2 distinct co-players AND Jaccard >= $1 (a floor that both prunes weak
-- edges and self-limits hub artists, whose large denominators drag their
-- Jaccard down) are kept. Completed plays only, 365-day window.
WITH user_artists AS (
    SELECT DISTINCT pe.user_id, t.artist_id
    FROM play_events pe
    JOIN tracks t ON t.id = pe.track_id
    WHERE pe.was_skipped = false
      AND pe.started_at > now() - interval '365 days'
),
artist_players AS (
    SELECT artist_id, count(*)::float8 AS players
    FROM user_artists
    GROUP BY artist_id
),
pairs AS (
    SELECT ua.artist_id AS a_id,
           ub.artist_id AS b_id,
           count(*)::float8 AS coplayers
    FROM user_artists ua
    JOIN user_artists ub
      ON ua.user_id = ub.user_id AND ua.artist_id <> ub.artist_id
    GROUP BY ua.artist_id, ub.artist_id
    HAVING count(*) >= 2
),
scored AS (
    SELECT p.a_id, p.b_id,
           p.coplayers / (pa.players + pb.players - p.coplayers) AS score
    FROM pairs p
    JOIN artist_players pa ON pa.artist_id = p.a_id
    JOIN artist_players pb ON pb.artist_id = p.b_id
)
INSERT INTO artist_similarity (artist_a_id, artist_b_id, score, source, fetched_at)
SELECT a_id, b_id, score, 'user_cooccurrence', now()
FROM scored
WHERE score >= $1
ON CONFLICT (artist_a_id, artist_b_id, source)
DO UPDATE SET score = EXCLUDED.score, fetched_at = EXCLUDED.fetched_at;
