/**
 * listAccess — access-scope query for list fan-out gating (D-04).
 *
 * getAccessibleListIds(userId) returns the set of list IDs a user can see:
 *   - Lists owned by the user (owner_id = userId)
 *   - Lists shared to the user via the list_shares join table
 *
 * The result is deduplicated. This is the gate used by the SSE endpoint
 * (Plan 06) to scope subscriptions: a subscriber receives events ONLY for
 * the list IDs returned here.
 *
 * Security invariant (T-04-02, T-04-03):
 *   A private list owned by another user with no list_shares entry for this
 *   user MUST NOT appear in the result.
 *
 * Exports: getAccessibleListIds
 * Source: RESEARCH.md Finding 3 verbatim pattern.
 */

import { eq } from 'drizzle-orm';
import { db } from '../db/client.js';
import { lists, listShares } from '../db/schema.js';

/**
 * Returns all list IDs accessible to userId:
 * owned lists UNION lists shared to this user, deduplicated.
 */
export async function getAccessibleListIds(userId: number): Promise<number[]> {
  const owned = await db.select({ id: lists.id }).from(lists).where(eq(lists.ownerId, userId));

  const shared = await db
    .select({ listId: listShares.listId })
    .from(listShares)
    .where(eq(listShares.userId, userId));

  const all = [...owned.map((r) => r.id), ...shared.map((r) => r.listId)];

  // Deduplicate (handles the degenerate case where a list is both owned and shared)
  return [...new Set(all)];
}
