-- M4b: ListenBrainz similarity ingest. Two symmetric tables — tracks and
-- artists — both keyed by (a_id, b_id, source) so the schema reserves room
-- for additional similarity sources (musicbrainz_tag, user_cooccurrence)
-- alongside listenbrainz. M4b only writes 'listenbrainz' rows.
--
-- The (a_id, score DESC) index satisfies M4c's hot path: "for seed S, give
-- me top-N similar tracks/artists descending by score."

CREATE TABLE track_similarity (
    track_a_id   uuid             NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
    track_b_id   uuid             NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
    score        DOUBLE PRECISION NOT NULL,
    source       TEXT             NOT NULL CHECK (source IN ('listenbrainz', 'musicbrainz_tag', 'user_cooccurrence')),
    fetched_at   timestamptz      NOT NULL DEFAULT now(),
    PRIMARY KEY (track_a_id, track_b_id, source),
    CHECK (track_a_id <> track_b_id)
);

CREATE INDEX track_similarity_a_score_idx
    ON track_similarity (track_a_id, score DESC);

CREATE TABLE artist_similarity (
    artist_a_id  uuid             NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
    artist_b_id  uuid             NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
    score        DOUBLE PRECISION NOT NULL,
    source       TEXT             NOT NULL CHECK (source IN ('listenbrainz', 'musicbrainz_tag', 'user_cooccurrence')),
    fetched_at   timestamptz      NOT NULL DEFAULT now(),
    PRIMARY KEY (artist_a_id, artist_b_id, source),
    CHECK (artist_a_id <> artist_b_id)
);

CREATE INDEX artist_similarity_a_score_idx
    ON artist_similarity (artist_a_id, score DESC);
