-- BUG B — calendars: add composite unique key (user_id, url).
--
-- Context (D-16): the two household members share ONE Fastmail account, so the
-- SAME collection URL is polled by both credentials. The calendar upsert keyed on
-- url alone never triggered onDuplicateKeyUpdate (no unique key on url), so every
-- poll inserted a fresh calendar row; the url-only lookup then resolved to the
-- other member's row, caching events under the wrong calendarId.
--
-- This migration is hand-written (not drizzle-kit generated) because drizzle-kit
-- push is unsafe on populated MariaDB (false destructive diffs) and there is no
-- migrations baseline. Apply it directly to the live DB before/with the image
-- rebuild that ships the schema + broker fixes.
--
-- Order matters: duplicate (user_id, url) rows must be collapsed BEFORE the unique
-- key is added, or ADD UNIQUE fails. We keep the LOWEST id per (user_id, url),
-- repoint any cached events from the loser rows onto the keeper, then delete losers.

-- 1. Repoint calendar_events from duplicate calendar rows onto the keeper
--    (lowest id) for each (user_id, url) group.
UPDATE calendar_events ce
JOIN calendars dup       ON dup.id = ce.calendar_id
JOIN (
  SELECT user_id, url, MIN(id) AS keep_id
  FROM calendars
  GROUP BY user_id, url
) keeper ON keeper.user_id = dup.user_id AND keeper.url = dup.url
SET ce.calendar_id = keeper.keep_id
WHERE ce.calendar_id <> keeper.keep_id;

-- 2. Delete the duplicate (loser) calendar rows, keeping the lowest id per group.
DELETE c FROM calendars c
JOIN (
  SELECT user_id, url, MIN(id) AS keep_id
  FROM calendars
  GROUP BY user_id, url
) keeper ON keeper.user_id = c.user_id AND keeper.url = c.url
WHERE c.id <> keeper.keep_id;

-- 3. Add the composite unique key that makes the upsert idempotent per (user_id, url).
ALTER TABLE calendars
  ADD CONSTRAINT uniq_calendar_user_url UNIQUE (user_id, url);
